首页 > 代码库 > 深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法

深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法

×
目录
[1]动态样式 [2]CSS类[3]setAttribute()[4]CSSRule对象添加[5]空样式覆盖[6]CSSRule对象删除

前面的话

  我们可以通过计算样式来读取伪元素的样式信息,但是却无法使用javascript来直接操作伪元素,本文以一个需求解决为例,详细介绍脚本化伪元素的6种方法

需求说明

  【1】为id=box的div元素添加content="前缀"的:before伪元素

  【2】为已经添加:before伪元素的div元素删除伪元素

   [注意]由于IE7-浏览器不支持:before伪元素,所以该需求兼容到IE8

 

添加伪元素

方法一:动态样式

  可以采用动态样式的方法,动态生成<style>标签及相关的伪元素样式内容

  由于IE8-浏览器将<style>标签当作特殊的节点,不允许访问其子节点及设置innerHTML属性,需要使用CSSStyleSheet对象的cssText属性来实现兼容

<div id="box">测试文字</div><button id="btn">添加伪元素</button><script>//添加伪元素function loadStyles(str){    //设置标记,防止重复添加    loadStyles.mark = load;    var style = document.createElement("style");    style.type = "text/css";    try{        style.innerHTML = str;    }catch(ex){        //IE8-浏览器兼容        style.styleSheet.cssText = str;    }    var head = document.getElementsByTagName(head)[0];    head.appendChild(style); }btn.onclick = function(){    //当样式表没有添加过时,添加    if(loadStyles.mark != load){        loadStyles("#box:before{content:‘前缀‘;color: red;}");            }}</script>        

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/mihjse0v" frameborder="0" width="320" height="240"></iframe>

方法二:添加自带伪元素的类名

  在处理大量CSS样式时,一般采用脚本化CSS类的方法。而添加伪元素,也可以使用类似的技术。把伪元素的样式挂在一个新类名上,然后把元素的className设置为新类名

<style>.add:before{content: "前缀";color: blue;}    </style><div id="box">测试文字</div><button id="btn">添加伪元素</button><script>btn.onclick = function(){    box.className = add;}</script>

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/8z5asuxb" frameborder="0" width="320" height="240"></iframe>

方法三:利用setAttribute()方法实现自定义伪元素内容

  若使用方法二,无法自定义伪元素的内容,拓展性不高

  伪元素的content属性非常强大,它的值可以有以下选择,关于content属性的详细信息移步至此

content:<string>|<uri>|attr(<identifier>)

  使用content属性中的attr()值配合setAttribute()方法就可以实现自定义伪元素的内容

  IE8-浏览器需要在元素特性中出现data-beforeData(设置为空字符串即可),才可以效果;其他浏览器无此问题

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

<!--为了兼容IE8-,需要在元素特性中设置 data-beforeData=""--><div id="box" data-beforeData="">测试文字</div><button id="btn">添加伪元素</button><script>btn.onclick = function(){ box.setAttribute(data-beforeData,前缀);}</script>

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/y8m5yxvj" frameborder="0" width="320" height="240"></iframe>

dataset

  HTML5新增了dateset数据集特性,将元素特性和对象属性联系在了一起

  [注意]IE10-浏览器不支持

  如果不考虑兼容,同样可以实现dateset来实现,但是由于dataset的解释规则,元素特性的值不可以出现大写,需要进行局部修改

  经测试,IE11浏览器不支持使用dateset动态修改伪元素

<style>#box:before{content: attr(data-before);color: red;}</style><div id="box">测试文字</div><button id="btn">添加伪元素</button><script>btn.onclick = function(){    box.dataset.before = 前缀;}</script>

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/eu4gqcic" frameborder="0" width="320" height="240"></iframe>

方法四:通过CSSRule对象添加样式

  虽然伪元素的样式无法通过操作行间样式来直接添加,但是可以通过CSSRule对象通过操作内部样式表实现

  如果存在内部样式表,即存在<style>标签,则直接在<style>标签中添加样式;否则先新建<style>标签,再添加样式

<div id="box">测试文字</div><button id="btn">添加伪元素</button><script>//作为存在<style>标签的标记,1表示存在,0表示不存在var mark = 0;var tags = document.getElementsByTagName(*);function addStyle(obj){    var str = #box:before{content:"前缀";color: pink;};    var sheet = obj.sheet || obj.styleSheet;    var rules = sheet.cssRules|| sheet.rules;    for(var i = 0,len = rules.length; i < len; i++){        //如果已经设置了:before伪元素的样式,就不再重复添加        if(/:before/.test(rules[i].selectorText)){            //obj.mark表示是否设置了:before伪元素的样式,1为已设置,0为未设置            obj.mark = 1;            break;        }    }    //如果未设置伪元素样式    if(!obj.mark){        if(sheet.insertRule){            sheet.insertRule(#box:before{content:"前缀";color:green;},0);        }else{            sheet.addRule(#box:before,content:"前缀";color:green;,0);        }    }}btn.onclick = function(){    for(var i = 0; i < tags.length; i++){        if(tags[i].nodeName == STYLE){            mark = 1;            //添加伪元素            addStyle(tags[i]);            break;        }    }    if(!mark){        //新建<style>标签        var ele = document.createElement(style);        document.getElementsByTagName(head)[0].appendChild(ele);        //添加伪元素        addStyle(ele);    }    }</script>    

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/2xdky4q5" frameborder="0" width="320" height="240"></iframe>

删除伪元素

  相比于新增伪元素来说,删除伪元素要困难一些。因为<style>元素中可能还有许多其他的样式,所以只能通过覆盖或删除指定样式来实现

方法一:空样式覆盖

  使用优先级更高的:before伪元素的空样式来覆盖原有样式

<style>#box:before{content:"前缀";color:green;}    .remove:before{content:""!important;}</style><div id="box">测试文字</div><button id="btn">删除伪元素</button><script>btn.onclick = function(){    box.className = remove;    }</script>    

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/vcqpxtuy" frameborder="0" width="320" height="240"></iframe>

方法二:通过CSSRule对象删除指定

  通过selectorText找出CSSRule对象中的:before伪元素的CSS规则

  [注意]在IE8浏览器中,:before伪元素选择器文本会自动将冒号置为单冒号,而其他浏览器会自动将冒号置为双冒号

  然后使用deleteRule()方法或removeRule()方法删除指定样式

<style>#box::before{content:"前缀";color:green;}    </style><div id="box">测试文字</div><button id="btn">删除伪元素</button><script>function deleteStyles(){    var sheet = document.styleSheets[0];    var rules = sheet.cssRules || sheet.rules;    for(var i = 0; i < rules.length; i++){        //找出伪元素        if(/#box:(:)?before/.test(rules[i].selectorText)){            if(sheet.deleteRule){                sheet.deleteRule(i);            //兼容IE8-浏览器            }else{                sheet.removeRule(i);            }            }    }}btn.onclick = function(){    deleteStyles();    }</script>

<iframe style="width: 100%; height: 60px;" src="http://sandbox.runjs.cn/show/etsidzzn" frameborder="0" width="320" height="240"></iframe>

最后

  脚本化CSS系列终于完结了,基本上把使用javascript操作CSS的内容都囊括了

  【1】脚本化行间样式

  【2】查询计算样式

  【3】脚本化CSS类

  【4】脚本化样式表

  【5】动态样式

  【6】脚本化伪元素

  欢迎交流

<script type="text/javascript">// 0){ return; } if(select[i].getBoundingClientRect().top <= 0 && select[i+1]){ if(select[i+1].getBoundingClientRect().top > 0){ change(oCon.children[i+2]) } }else{ change(oCon.children[select.length+1]) } }}document.body.onmousewheel = wheel;document.body.addEventListener(‘DOMMouseScroll‘,wheel,false);var oCon = document.getElementById("content");var close = oCon.getElementsByTagName(‘span‘)[0];close.onclick = function(){ if(this.innerHTML == ‘显示目录‘){ this.innerHTML = ‘ב; this.style.background = ‘‘; oCon.style.border = ‘2px solid #ccc‘; oCon.style.width = ‘‘; oCon.style.height = ‘‘; oCon.style.overflow = ‘‘; oCon.style.lineHeight = ‘30px‘; }else{ this.innerHTML = ‘显示目录‘; this.style.background = ‘#3399ff‘; oCon.style.border = ‘none‘; oCon.style.width = ‘60px‘; oCon.style.height = ‘30px‘; oCon.style.overflow = ‘hidden‘; oCon.style.lineHeight = ‘‘; }}for(var i = 2; i < oCon.children.length; i++){ oCon.children[i].onmouseover = function(){ this.style.color = ‘#3399ff‘; } oCon.children[i].onmouseout = function(){ this.style.color = ‘inherit‘; if(this.mark){ this.style.color = ‘#3399ff‘; } } oCon.children[i].onclick = function(){ change(this); } }function change(_this){ for(var i = 2; i < oCon.children.length; i++){ oCon.children[i].mark = false; oCon.children[i].style.color = ‘inherit‘; oCon.children[i].style.textDecoration = ‘none‘; oCon.children[i].style.borderColor = ‘transparent‘; } _this.mark = true; _this.style.color = ‘#3399ff‘; _this.style.textDecoration = ‘underline‘; _this.style.borderColor = ‘#2175bc‘; }// ]]></script>

深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法