雖然標題裏寫的是僞元素
,不過這篇文章主要是說::before
和::after
,其他幾個僞元素(::first-letter
、::first-line
、::selection
等)因爲沒有content
屬性,因此本文一筆帶過,其實方法是同樣的。
僞元素的重點在於一個僞,雖然它們能夠被瀏覽器渲染引擎識別並正確渲染,然而僞元素自己並非DOM元素,因此沒法被js直接操做——所以任何基於JS直接選取DOM元素的CSS更改方法對僞元素都不起做用。(JQ看似萬能,這個問題上是直接就栽了。由於JQ的選擇符都是基於DOM元素)關於JS和JQ選擇器,能夠參考這兩篇文檔: Selectors API Level 1、jQuery Selectorsjavascript
雖然JS裏沒有能夠直接操做僞元素的選擇符,然而獲取其CSS屬性的方法仍是有的。php
利用window.getComputedStyle
方法選擇到僞元素,而後利用getPropertyValue
方法獲取對應的屬性的值。
根據MDN的文檔,css
window.getComputedStyle(element[, pseudoElt]);
此方法包含兩個參數,一個是元素自己另外一個是元素的僞元素。
js語法實例(完整DEMO在線連接):html
var div=document.querySelector('div'); var fontSize=window.getComputedStyle(div,'::before').getPropertyValue('font-size');//獲取before僞元素的字號大小
關於這個方法,詳解能夠參考這篇文章:
獲取元素CSS值之getComputedStyle方法熟悉java
window.getComputedStyle
方法雖然能夠獲取到僞元素的屬性值,然而根據該方法名字也知道其只能獲取CSS樣式,並沒有法更改css屬性,那麼若是想要用js動態更改僞元素屬性值的話,該怎麼處理呢?
思路有如下幾個:jquery
js更改data-*
屬性值來更改僞元素的content
值css3
建立多個class
,經過切換class
來達到改變樣式的目的git
利用CSSStyleSheet的insertRule
方法來添加樣式github
利用內部css樣式的高優先級來覆蓋外部csschrome
以上實現思路的推薦程度依次遞減
data-*
屬性來更改content
的值data-*
是HTML5新增的DOM元素屬性,做用大體能夠理解爲標記。具體用法能夠參考MDN的這篇文章.而僞元素的content
屬性值除了常規賦值外,還有一種特殊的attr()
方法來獲取。
HTML:
<div class="test" data-text="TEXT" data-color="red"></div>
CSS:
.test::before{ content: attr(data-text); }
結果:
TEXT
另外content
其實能夠多個attr連寫,並且attr()內的能夠是DOM元素的任意屬性(好比class
等,甚至非W3C標準屬性也支持,不過不推薦這麼作)因此很方便湊一些模版文字。像下面這種寫法也是徹底沒問題的。注意用空格鏈接,不要用"+"號。
EXAM:
.test::before { content: '個人類是' attr(class) '想要變成' attr(data-color); }
雖然W3C給
attr()
賦予了無限可能性,包括color
,width
等屬性在將來都有但願用這個方法更改,然而目前只有content
支持該方法,其他的都仍是草稿狀態,還沒有有瀏覽器支持。之因此把這個方法放在第一位只是由於相比別的實現手法來講,這個方法真的太簡單太優雅。
可是若是真的想要改僞元素裏的color
等元素呢?
class
來實現僞元素樣式的更改把這個方法放到推薦位第二位估計會被不少人罵我:「臥槽,這麼簡單又沒逼格的辦法你居然放到第二位!太沒水平了」。不過再看完後面兩種方法後或許你會對這種見解有所改觀。
這個方法的優勢是簡單好用且無兼容性問題。缺點是多了一些其實用處不大的class
,很像是jQuery類選擇器中毒患者的作法;另外不適合多狀態的場景(好比實時改變僞元素文字大小等)。
實現過於簡單就不貼代碼了。
前面的class切換大法
可能讓人感受不痛快,這裏來個高大上(僞)點的方法:
insertRule
方法來添加樣式這部份內容和W3C標準牽連比較多,加上較冷門,沒多少人關注,我的目前啃不動標準,因此這部份內容不會作深刻分析,理解可能也會有問題,望斧正。
CSSStyleSheet是瀏覽器存放頁面內全部css樣式表的對象方法(不包括行內樣式),每一個link
和style
標籤都表明一個CSSStyleSheet對象,獲取他們能夠用document.styleSheets
方法。(須要注意的是雖然styleSheets
方法返回的結果把link
標籤引進的外部樣式也算進去了,可是非IE瀏覽器沒辦法獲取到他們的cssRules
屬性,只有內嵌的style
標籤內的元素能夠被獲取到)
document.styleSheets[0].insertRule('.test::before{color:green}',0)//chrome,firefox等非IE瀏覽器使用 document.styleSheets[0].addRule('.test::before{color:green}',0)//IE系列瀏覽器使用 /* 雖然部分瀏覽器也能夠經過id來指定,'document.styleSheets.id.insertRule()'這種寫法在chrome和IE下都行得通,可是firefox會返回'undefined',因此建議仍是使用index值來獲取stylesheet */
.insertRule
的語法是stylesheet.insertRule(rule, index)
,另外一個參數是index
,意思是在對應的styleSheets裏的cssRules
樣式表中的位置,這個值越大則樣式優先級越高,可是值不能超過當前樣式表規則(cssRules
)長度(CSS中先定義的樣式老是會被後定義的覆蓋就是這個緣故。),當值小於cssRules
長度時,添加的樣式規則會插入到index
值定義的位置,以前其他的規則依次順延。
addrule
和insertRule
方法本質上沒區別,只是後者不被IE瀏覽器識別,因此前者做爲瀏覽器兼容方法存在。(下文爲節省篇幅,以insertRule
方法指代此兩種方法。)
上面的代碼看似簡單一行,然而卻不是每次都有效的。緣由有如下幾點:
document.styleSheets
雖然按照style
和link
的順序返回對應的StyleSheetList
,然而第一個若是是link
而不是style
,前面講過此時沒法獲取對應的cssRules
,則document.styleSheets[0].cssRules
爲null
,insertRule
方法不起做用。(此狀況只針對非IE瀏覽器,IE瀏覽器正常,可是定義的早每每意味着被後面的樣式覆蓋,因此意義不大)
同上,若是頁面內沒有內嵌樣式的style
標籤,則insertRule
方法也沒法發揮做用。
index
值不夠大的話頗有可能會早於css文件開始的定義位置,致使被覆蓋。所以有個折衷辦法就是給添加的樣式增長!important
,雖然我我的比較反感這麼作。
因而可知此方法的侷限性,可是這種方法的優雅之處在於避免了直接寫內嵌樣式,而是經過css api來作更改。相比下面的方法來講,稍微好點。
可是這種方法好像侷限性有點大啊?
HEAD
中添加style
標籤強制覆蓋初始屬性這個方法是利用內部css樣式的高優先級來覆蓋外部css,好處是簡單易理解,實現簡單。壞處就是吃相太難看,過於粗暴。
var style=document.createElement('style'); style.innerHTML=".test::before{color:green}";//添加樣式內容的話也能夠用上面提到過的`insertRule`,相對例子裏的硬編碼會更優雅點。 document.head.appendChild(style);
看到這裏可能有些人反應過來了,其實加style
標籤這種方法能夠是insertRule
實現方法的大前提——由於不是全部頁面一開始都有內嵌的style
樣式的。這種方法雖然不是很好,可是有時候卻又確確實實是必須的——好比「拖動滑塊改變僞元素內文字大小」這個需求。
拖動滑塊改變僞元素內的文字大小
且僞元素內隨時顯示當前字號
經過一個按鈕能夠改變僞元素內文字顏色
這個需求能夠將本文前面提到的四種改變僞元素樣式的方法都塞進去。具體實現參照DEMO,再也不作具體分析:
http://codepen.io/chitanda/pen/OVBJEw/
getComputedStyle()
attr-notation
CSSRules