css中的::after和::before已經被大量地使用在我們日常開發中了,使用他們可以使我們的文檔結構更加簡潔。但是很多人對::after和::before仍不是特別了解,究竟他們是做什么的?如何使用他們?什么時候應該使用他們?筆者總結了一些對偽元素的理解和使用經驗。
一、概念:
1.定義
The CSS ::before(::after)
pseudo-element matches a virtual first(last) child of the selected element. It is typically used to add cosmetic content to an element by using the content
CSS property. This element is inline by default.
從定義我們知道::before和::after匹配一個虛擬元素,主要被用於為當前元素增加裝飾性內容的。他顯示的內容是其自身的“content
”屬性,默認是內聯元素。
其實::after和::before被引入css中,最核心的目的,還是為了實現語義化。在我們實際開發時候經常有這樣的經歷,為了實現一些效果,在文檔中創建了一些沒有實際內容的節點,或者加入輔助樣式的文本,如:
<style> ul{ list-style: none; } li{ display: inline; } </style> <nav> <ul> <li>HTML 5</li> <li>|</li> <li>CSS3</li> <li>|</li> <li>JavaScript</li> </ul> </nav>
顯示的時候是這樣子的:
很明顯,例子中的“|”僅是顯示時候用的間隔符,沒有實際的意義,而他所在的li元素僅是為了裝飾才被創建的,本是不應該被創建在文檔內的。那么能不能由樣式(css)去創建出節點把他們代替掉呢?
出於這樣的需求,就誕生了::after和::before,這兩個偽元素相當於是對當前元素的裝潢,他們並不是節點,不會出現在dom樹中,但是在顯示上具備節點的效果。我們使用::after和::before重構一下上邊的代碼:
<style> ul{ list-style: none; } li{ display: inline; } li:not(:last-child)::after{ content: "|"; } </style> <nav> <ul> <li>HTML 5</li> <li>CSS3</li> <li>JavaScript</li> </ul> </nav>
顯示效果沒有變化,但是文檔結構變得清晰了多了。
2.使用
::after和::before的使用很簡單,可以認為其所在元素上存在一前一后的兩個的元素,這兩個元素默認是內聯元素,但我們可以為其增添樣式。::after和::before使用的時候一定要注意,必須設置content,否則這兩個偽元素是無法顯示出來的。而content屬性,會作為這兩個偽元素的內容嵌入他們中。如果不需要偽元素的內容,可以將content設置為'',但是不設置的話,偽元素就會無效。如:
<style> p:before{ content: "H"; p:after{ content: "d"; } </style> <p>ello Worl</p>
顯示為完整的Hello World。
::after和::before是虛擬元素,不會影響真正元素的所在文檔的位置,對:first-child或者:last-child這種偽類選擇不會造成影響。
3.操作
::after和::before是虛擬節點,而不是正在的節點,不在documont里面找到對應Node對象,在之前的例子中,我們執行下列js代碼:
console.log( document.querySelector("ul").childNodes);
得到的是一個只有3個節點的NodeList對象,而兩個偽元素並不在對象中。因為::after和::before不是真正的節點,所以我們取不到他們,也不發設置點擊等用戶事件。::after和::before雖然是不能設置事件,但還會捕獲用戶事件,並把事件“冒泡”到偽元素所在的元素上。之所以“冒泡”二字加了引號,是因為他不是真的冒泡,更准確的說::after和::before幫所在元素去捕獲去事件,事件的srcElement對象是偽元素所在的元素,而不是偽元素本身。
document不能獲取到::after和::before所對應的節點對象,但是可以通過css的接口獲取其樣式屬性,如:
window.getComputedStyle( document.querySelector('li'), ':before' )
返回是個CSSStyleDeclaration對象,可以獲取當前的style值。
另外,content屬性京城配合attr()函數使用,attr()函數用來獲取html元素指定屬性的值,eg: .wcs:before{ content:attr(title); color:red; } <div class="wcs" title="第五部分"> 王船山的美學思想 </div>
二、分享一些::after和::before使用的經驗
以下例子多數是在特定平台上使用過的,未做兼容處理,建議在chrome下瀏覽
1.間隔符用法
如文章最開始的例子,使用::after偽元素做間隔符,並使用偽類:not排除掉最后一個元素。
2.做border三角圖標
很多開發者都用過border做的三角圖標,本身三角符號就不屬於文檔,使用偽元素做三角符最合適了。
3.字符圖標
最近筆者在開發微信小程序,因為微信小程序不支持svg和背景圖,於是筆者大量使用字符圖標,感覺字符圖標非常方便,就是受設備系統字體庫限制。
4.webfont的圖標
現在webfont圖標的最佳實踐就是使用i標簽和::after或者::before,實現這種圖標最佳實踐的工具非常多,比如http://fontello.com/,從這個網站我們可以下載svg的圖標庫。這種例子太多了,這里就不再列舉。
5.做單位、標簽、表單必填標准
筆者一直認為表單輸入框的必填標記(往往是紅色的“*”字符),不應該放到文檔當中,使用::before可以很優雅地解決這個問題(其實就是字符圖標的進一步應用)。
對於單位和前(后)置標簽,也可以這樣做。但是多數情況下不推薦這種做法,因為單位和標簽應該是文檔的一部分。
6.做一些效果
可以參考《理解偽元素 :before 和 :after》這篇文章的效果,筆者曾經在實際項目中使用過“迷人的陰影”效果,也曾在微場景開發中實現過一些類似的動畫。
7.實現一些標簽對placeholder的支持
只有幾個標簽支持placeholder,而且如<input type='date' />雖然是input但是也不支持。使用::before可以讓一部分標簽也實現對placeholder屬性的支持。
8.實現文字圖片居中對齊
優雅地實現張鑫旭老師的inline-box居中方法,使用一個高度為100%的::before將自身的對齊線移動到自己的中線,這樣里面的所有內聯元素都居中對齊了。
9.清除浮動
即對浮動盒子的父元素設置:after產生一個偽元素,用這個偽元素清除浮動,這樣就不需要在浮動元素后面新增一個空元素了。這個很常用,bootstrap的clearfix類就是使用這個方法。
10.使用pointer-events消除偽元素事件
之前提到過,偽元素::after和::before會替所在元素捕獲用戶事件,有時候這並非我們想要的,因為這樣會影響被::after和::before覆蓋的子節點或者兄弟節點捕獲用戶事件,使用pointer-events可以消除這種問題。
所有例子的源碼在https://github.com/laden666666/css-before-and-after-test
簡單就分享這么多,總之使用偽元素的核心是更利於語義化,這是我們活用::after和::before的前提,否則就是胡亂使用了。總體可以分為四種用法:
1.用css創建裝飾性元素
2.用css創建用於布局的元素,實現特殊布局的特殊需要
3.做顯示圖標的實現手段
4.配合attr顯示屬性值
參考:
http://www.webhek.com/pseudo-element/
http://www.cnblogs.com/ys-ys/p/5092760.html
https://developer.mozilla.org/en-US/docs/Web/CSS/::after
--------------------- 本文來自 馬大頭 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/w405722907/article/details/79446038?utm_source=copy