原生js获取css伪类元素并设置属性

改编自

一、伪元素有哪些

首先,先简单说一下伪元素都有哪些。伪元素有六个,分别是 ::after::before::first-line::first-letter::selection::backdrop

在各大网页中最常用的伪元素,是::after::before

这几个伪元素的语意可参考另外一篇文章《CSS伪元素选择器 总结》。

CSS3中,建议伪元素使用两个冒号(::)语法,而不是一个冒号 (😃,目的是为了区分伪类和伪元素。大多数浏览器都支持这两种表示语法。只有 ::selection 永远只能以两个冒号开头(:😃。因为IE8只支持单冒号的语法,所以,如果你想兼容IE8,保险的做法是使用单冒号。

二、获取伪元素的属性值

获取伪元素的属性值可以使用 window.getComputedStyle() 方法,获取伪元素的CSS样式声明对象。然后利用getPropertyValue()方法或直接使用键值访问都可以获取对应的属性值。

语法:window.getComputedStyle(element[, pseudoElement])

参数如下:

element(Object):伪元素所在的DOM元素;
pseudoElement(String):伪元素类型。可选值有:”:after”、”:before”、”:first-line”、”:first-letter”、”:selection”、”:backdrop”;

举个例子:

// HTML代码
<div id="myId"></div>

// CSS代码
#myId:before {
content: "hello world!";
display: block;
width: 100px;
height: 100px;
background: red;
}

// JS代码
var myIdElement = document.getElementById("myId");
var beforeStyle = window.getComputedStyle(myIdElement, ":before");
console.log(beforeStyle); // [CSSStyleDeclaration Object]
console.log(beforeStyle.width); // 100px
console.log(beforeStyle.getPropertyValue("width")); // 100px
console.log(beforeStyle.content); // "hello world!"

备注:

1.getPropertyValue()和直接使用键值访问,都可以访问CSSStyleDeclaration Object。它们两者的区别有:

  • 对于float属性,如果使用键值访问,则不能直接使用getComputedStyle(element, null).float,而应该是cssFloat与styleFloat;
  • 使用键值,则属性的键需要使用驼峰写法,如:style.backgroundColor
    使用getPropertyValue(), 不用驼峰,例如:style.getPropertyValue(“border-top-color”)
  • getPropertyValue()方法在IE9+和其他现代浏览器中都支持;在IE6~8中,可以使用getAttribute()方法来代替;

2.伪元素默认是”display: inline”。如果没有定义display属性,即使在CSS中显式设置了width的属性值为固定的大小如”100px”,但是最后获取的width值仍是”auto”。这是因为行内元素不能自定义设置宽高。解决办法是给伪元素修改display属性为”block”、”inline-block”或其他

三、更改伪元素的样式

方法1. 更换class来实现伪元素属性值的更改:

举个栗子:

// CSS代码
.red::before { 
content: "red"; 
color: red; 
}
.green::before { 
content: "green"; 
color: green;
}
// HTML代码
<div class="red">内容内容内容内容</div>
// jQuery代码
$(".red").removeClass('red').addClass('green');

1234567891011121314

方法2. 操作 document.styleSheets

Document.styleSheets 只读属性,返回一个由 StyleSheet 对象组成的 StyleSheetList,每个 StyleSheet 对象都是一个文档中链接或嵌入的样式表。 ——MDN

document.styleSheets的大概结构

  document.styleSheets = {
    CSSStyleSheet_0: {
      cssRules: {
        selectorText: '', // selector名字,比如div            
        style: {}  // 具体样式
      },
      rules: {},
      ...
    },
    CSSStyleSheet_1...
  }

CSSStyleSheet的样子

image-20220501182651042

insertRule(rule [,index])deleteRule(index)
添加的rule,优先级特性跟css的一样: 先看优先级, 同优先级的index靠后的优先

document.styleSheets[0].cssRules.length     // 已经定义好的 css 规则数
document.styleSheets[0].cssRules			// 已经定义好的 css 规则的 array
document.styleSheets[0].cssRules			// 已经定义好的 css 规则的 array
document.styleSheets[0].insertRule(cssRule, index)	


let index = document.styleSheets[0].cssRules.length  // 查看现有的css数组的length
document.styleSheets[0].insertRule('html::after {animation-name:test;animation-duration: 1s;animation-timing-function: ease-in-out;border: 10px solid red;}', index); // 在现有的css数组的末尾, 添加一个新的css rule

MDN官网的示例function: Function to add a stylesheet rule

/**
 * Add a stylesheet rule to the document (it may be better practice to dynamically change classes, so style information can be kept in
 * genuine stylesheets and avoid adding extra elements to the DOM).
 * Note that an array is needed for declarations and rules since ECMAScript does not guarantee a predictable object iteration order, and since CSS is
 * order-dependent.
 * @param {Array} rules Accepts an array of JSON-encoded declarations
 * @example
        addStylesheetRules([
          ['h2', // Also accepts a second argument as an array of arrays instead
            ['color', 'red'],
            ['background-color', 'green', true] // 'true' for !important rules
          ],
          ['.myClass',
            ['background-color', 'yellow']
          ]
        ]);
*/
function addStylesheetRules (rules) {
  var styleEl = document.createElement('style');

  // Append <style> element to <head>
  document.head.appendChild(styleEl);

  // Grab style element's sheet
  var styleSheet = styleEl.sheet;

  for (var i = 0; i < rules.length; i++) {
    var j = 1,
        rule = rules[i],
        selector = rule[0],
        propStr = '';
    // If the second argument of a rule is an array of arrays, correct our variables.
    if (Array.isArray(rule[1][0])) {
      rule = rule[1];
      j = 0;
    }

    for (var pl = rule.length; j < pl; j++) {
      var prop = rule[j];
      propStr += prop[0] + ': ' + prop[1] + (prop[2] ? ' !important' : '') + ';\n';
    }

    // Insert CSS Rule
    styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);
  }
}
posted @ 2022-05-02 09:29  mayingdts  阅读(3755)  评论(0编辑  收藏  举报