1. 程式人生 > >js設定before和after偽元素效果的方法總結

js設定before和after偽元素效果的方法總結

我們知道,我們無法直接給before和after偽元素設定js效果
例子說明
現在需要為(id為box,內容為"我是測試內容"的div)新增(:before內容為"字首",顏色為紅色的偽元素)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="box">我是測試內容</div>
  <script>
    var oBox = document.getElementById('box');
  </script>
</body>
</html>

解決辦法

【方法一】動態嵌入css樣式

IE8-瀏覽器將<style>標籤當作特殊的節點,不允許訪問其子節點。IE10-瀏覽器支援使用styleSheet.cssText屬性來設定樣式。相容寫法如下:
< script >
function loadStyleString(css) {
    var style = document.createElement("style");
    style.type = "text/css";
    try {
        style.appendChild(document.createTextNode(css));
    } catch(ex) {
        style.styleSheet.cssText = css;
    }
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(style);
}
loadStyleString("#box:before{content:'字首';color: red;}"); 
< script > 


 
【方法二】新增自帶偽元素的類名

<style>
    .change:before{content: "字首";color: red;}
</style>

<script>
    oBox.className = 'change';
</script> 

[缺點]此方法無法控制偽元素裡面的content屬性的值

 
【方法三】利用setAttribute實現自定義content內容

<style>
  .change:before{content: attr(data-beforeData);color: red;}
</style>

<script>
    oBox.setAttribute('data-beforeData','字首');
</script>

[注意]此方法只可用setAttribute實現,經測試用dataset方法無效

 
【方法四】新增樣式表



firefox瀏覽器不支援addRule()方法,IE8-瀏覽器不支援insertRule()方法。相容寫法如下:


<script>
    function insertRule(sheet,ruleKey,ruleValue,index){
      return sheet.insertRule ? sheet.insertRule(ruleKey+ '{' + ruleValue + '}',index) : sheet.addRule(ruleKey,ruleValue,index);
  } 
    insertRule(document.styleSheets[0],'#box:before','content:"字首";color: red;',0)    
</script>


[缺點]該方法必須有內部<style>或用<link>連結外部樣式,否則若不存在樣式表,則document.styleSheets為空列表,則報錯


【方法五】修改樣式表

先使用方法四新增空的樣式表,然後獲取新生成的<style>並使用其innerHTML屬性來修改樣式表

<script>
function loadStyleString(css){
    var style = document.createElement("style");
    style.type = "text/css";
    try{
        style.appendChild(document.createTextNode(css));
    }catch(ex){
        style.styleSheet.cssText = css;
    }
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(style);
}
loadStyleString('');
document.head.getElementsByTagName('style')[1].innerHTML = "#oBox:before{color: " + colorValue + ";}";
</script>

[注意]只能使用getElementsByTagName('style')[1]的方法,經測驗使用stylesheets[1]方法無效




js如何控制css偽元素(before,after)

曾經遇到的問題,在對抗UC瀏覽器遮蔽需要把內容輸出到css 偽元素中輸出。有個疑問如何用js控制它。於是在segmentfault提問,如下是對問題的整理:

    如何用js控制css偽類after

簡單粗暴的方式:

簡單粗暴的方式,直接在html中新增樣式覆蓋掉之前樣式規則

<style>
    p:after{content:'我是字尾'}
</style>
<p>正文內容</p>

<script>
var css=function(t,s){
    s=document.createElement('style');
    s.innerText=t;
    document.body.appendChild(s);
};

document.onclick=function(){
    css('p:after{content:\'修改一下\'}');
};
</script>

進化版

這樣寫了功能實現了,優雅欠佳,作為進化版,其實就是用class名來重寫樣式,

p:after{content:'我是字尾'}
p.change{content:'我是修改過的字尾'} (這裡是不是該改為 p.change:after{content:'我是修改過的字尾'} )

只要在需要的時候,給p標籤新增change這個class就可以實現替換的目的。原理和第一個沒什麼區別。這樣寫的好處是,改變起來更優雅靈活,用class做了個鉤子。

再進化版

上個版本已經解決了切換的問題,如果有更多可以不斷的切換class,但是想下這種方式也還是有點笨重,因為可能要寫很多css,如果是想換的內容是不確定的,需要用變數來處理呢?這時候,可能會想到用 第一種方法就可以了,但是第一種方式真的不是很優雅。還有什麼方式呢?
在css中,偽元素的content是能讀取到data屬性的。
也就是說我們可以這樣寫css

p:after {
    content: attr(data-content);
}
在進化版是第二版的變種,
css檔案
p.change:after {
    content: attr(data-content);
}
js檔案
$(this).addClass('change').attr('data-content', content);
這樣你就可以隨意改動了。
最後一種方法是由bumfod提供方法很hack了,遍歷了所有的css文件,找到偽元素,然後更改,有興趣的同學可以嘗試下