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


    前面的话

      我们可以通过计算样式来读取伪元素的样式信息,但是却无法使用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>        

    添加自带伪元素的类名

      在处理大量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>

    利用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>

    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>

    通过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>    

    删除伪元素

      相比于新增伪元素来说,删除伪元素要困难一些。因为<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>    

    通过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>

    最后

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

      【1】脚本化行间样式

      【2】查询计算样式

      【3】脚本化CSS类

      【4】脚本化样式表

      【5】动态样式

      【6】脚本化伪元素

      欢迎交流

  • 相关阅读:
    三、瀑布流中的ajax请求详解 Confi
    显示GridControl的横向滚动条
    耳目一新的感觉(转)
    JavaScript学习笔记——变量,作用域和内存管理
    Servlet编程笔记
    JavaScript,应该选择内嵌形式还是外链形式(Inline Code Versus External Files)
    JavaScript学习笔记——Javascript基本语法
    为主机空间添加一个phpmyadmin
    关于Post中明文传送密码以及其他
    Maven原理和Maven2新特性
  • 原文地址:https://www.cnblogs.com/xiaohuochai/p/5851807.html
Copyright © 2020-2023  润新知