参考链接:

  • segmentfault
  • MDN CSSStyleSheet

QQ群闲逛,看到有人说js不能操作css的伪元素样式,
之前没有遇到过应用场景,我当时想到的就是操作通过操作class来控制样式
然后网上搜集一些资料,结合自己理解做个整理

关于样式

定义不同的class

给元素定义多个class, 根据class定义不同的伪元素,通过对class的操作间接实现对伪元素的操作

示例:

<div class="style --a">... ...
</div>
.style.--a::before {content: 'a';color: red;
}
.style.--b::before {content: 'b';color: green;
}

替换style

style节点也算是dom的一部分,直接替换style, 缺点是不支持引入的css

举个简单的例子

<head><style>.style::before {content: 'prefix'}</style>
</head>
<body><div class='style'>... ...</div>
</body>
document.documentElement.querySelector('style').innerText=`.style::before {content: 'ok!'}`

操作 document.styleSheets

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

贴一个document.styleSheets的大概结构

// document.styleSheets
{// CSSStyleSheet{// 这里我发现cssRules和rules内容几乎一样// 把实现代码的cssRules换成rules依旧ok// MDN发现rules和cssRules都是CSSRuleList的实现// rules是遗留属性,用的时候还是操作cssRules好了cssRules: { // 选择器名字,比如div// 原理就是遍历所有的selectorText,匹配了就返回这个cssRules在操作styleselectorText: ''// 具体样式style: { }},rules: { },...},CSSStyleSheet...
}

下面的实现函数参数(selector)都表示一个选择器,得是你自己定义过的, 要注意优先级问题

比如 div::after 、.box::before 、:root body > div…

以下两个实现方式都不支持!impotant

js实现一

// 这个是直接从评论区copy的,看不懂 (菜...
// ta这个直接取最后一条CSSStyleSheet再把修改里面所有对应的rule的style, 不用考虑同级 顺序引起的优先级问题
// 解释↑, 你selector传的啥就找到啥,传个div就找div,定义的样式优先级只是给div这个规则用,不包含html div
// 用法: ruleSelector(selector).slice(-1).forEach(function (rule) { rule.style.xx... })
function ruleSelector(selector) {function uni(selector) {// 在评论区提供的一个链接(stackOverflow)找到一段跟这一样的代码,多了个注释 // for firefox// 看了下时间12年左右,应该那时候有点兼容性的问题,不过我现在试了下 直接返回selector不做处理是正常使用的return selector.replace(/::/g, ':')}// 把符合的CSSStyleSheet(就是这里面包含selector的)返回为一个集合return Array.prototype.filter.call(Array.prototype.concat.apply([], Array.prototype.map.call(document.styleSheets, function (x) {return Array.prototype.slice.call(x.cssRules);})), function (x) {return uni(x.selectorText) === uni(selector)})}

js实现二

// 自己写的一个方法, 就是遍历所有的样式规则,匹配到符合的就返回
// 缺点就是有个同级顺序优先级问题,这个只是把找到的第一个符合的rule返回出来
// 操作的时候直接 ruleSelector(selector).style....
function ruleSelector(selector) {for (const styleSheet of document.styleSheets) {for (const rule of styleSheet.cssRules) {// 找到一个返回就行if (rule.selectorText === selector) {return rule}}}
}

insertRule or addRule (也算是操作document.styleSheets)

看mdn的文档发现stylesheet还有这两个api,

前三种属于修改,这种属于添加,利用优先级特性也可以间接达到修改伪元素样式的目的

下面每个函数的index参数不能大于总规则数(CSSRuleList.length), 也不能小于0,

简单来说就是得在CSSRuleList数组范围内

需要用的话直接insertRule和deleteRule就ok,

addRule和removeRule属于遗留方法,不建议使用

标准方法

insertRule

最终操作的是 CSSRuleList(cssRules和rules都继承于这个,相当于同时操作这两个)

stylesheet.insertRule(rule, index)
// rule: 就是一条完整的css样式规则(选择器 属性), 比如 p::before {color: red;font-Size:2rem}
// index: index表示插入的位置,默认是0,就是第一个// 实例
document.styleSheets[0].insertRule('div::before { color: green ; font-Size:2rem}')

缺点就是有点麻烦

MDN封装了一个函数, (同级选择器 优先级最高)

// 这个就是添加一个style节点, 可以添加一些自定义的规则
// 参数rules为一个数组,第一个索引为选择器,后面的都表示为样式规则
// 举个例子
// addStylesheetRules(['div::before'], ['color','red', true],['font-Size','2rem'])
// 最终效果就是在head里面添加一个style节点,选择器为div::before, 两条规则,数组第三个传true表示!important
function addStylesheetRules (rules) {var styleEl = document.createElement('style');// Append <style> element to <head>document.head.appendChild(styleEl);// Grab style element's sheetvar 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 RulestyleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);}
}

deleteRule

只支持通过下标移除规则

stylesheet.insertRule(index)

遗留方法

addRule

向样式表添加一条新规则,需要提供应用样式的选择器和应用在匹配元素上的样式块 ——MDN

cssStyleSheet.addRule(selector, styleBlock, index);
// selector: 选择器, div div::after > + ...
// styleBlock: 样式, 不加{}
// index: 索引
// 只返回-1,没实际意义// 示例
document.styleSheets[0].addRule('P::before', 'color:red;font-size:2rem')

removeRule

跟deleteRule用法一致

cssStyleSheet.removeRule(index)

关于如何给伪元素添加事件

… …

这个暂时没什么好办法。

假设一个场景,需要给控制伪元素的点击事件

可以把给伪元素的容器设置一个点击事件

这时会发现伪元素和容器内其他元素都都会触发点击事件,

然后给容器设个禁止点击事件

再给伪元素设置允许点击事件

通过修改伪元素容器的点击事件来间接达到修改伪元素的点击事件

举个简单例子

<!DOCTYPE html>
<html>
<head><style>div {pointer-events: none; // 禁止被点击}div::before {content: '❤️';pointer-events: auto; // 允许被点击}</style>
</head>
<body><div>... ...</div><script>let div = document.querySelector('div')// 要修改伪元素点击事件的话这样修改这个div的就好了div.onclick = function() {alert('555')}setTimeout(function() {div.onclick = function() {alert('ok!')}},2000)</script>
</body>
</html>

拓展知识

大意就是之前有个方案可以通过这个api来操作伪元素样式

JS操作CSS伪元素相关推荐

  1. [JS 分析] 汽_车_之_家 JS 生成 CSS 伪元素 hs_kw44_configUS::before

    0.参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements https://developer.mozilla.org/ ...

  2. jquery改变选中对象的css,使用jQuery选择和操作CSS伪元素,例如:: before和:: after

    DIEA 您认为这将是一个简单的问题,jQuery可以做的其他事情.不幸的是,问题归结为一个技术问题:css:after和:之前规则不是DOM的一部分,因此不能使用jQuery的DOM方法进行更改.有 ...

  3. 如何修改css伪元素的样式

    首先说一下变成思想,众所周知,css伪元素是不可以修改的,首先你查找他的元素就很困难,不知道怎么查找的可以看一下我的另一篇原生js查看css伪元素属性,那么我们应该怎么修改呢 . 其实换一种思维事情就 ...

  4. html 的css骚操作,意想不到的 CSS 伪元素 before/after 各种骚操作 - 文章教程

    CSS 伪元素 before/after 我们经常用到,常见的就是画个三角形.绘画背景阴影等,这篇文章将给大家分享还有很多有趣的操作,比如画线画图标等. 画细线 普通的 border 最小高度为1px ...

  5. CSS伪元素::before,::after

    W3C的解释用一句话概括:单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素中. css伪元素,之所以被称为伪元素,是因为他们不是真正的页面元素,html页面中没有对应的元素,但是其所有用 ...

  6. JavaScript 如何使用JS操作CSS

     家人们,新的一天新的知识点,我们要开启新的课程啦,今天带大家学习如何使用JS操作css,大家有不懂得可以私信我,或者在下方评论噢,现在就让我带你们进入知识的海洋中. 一.什么是css? Cascad ...

  7. 【伪类与伪元素】用CSS伪元素(以:before为例)插入图片

    [伪类与伪元素]用CSS伪元素(以:before为例)插入图片 对于一些小图标类型的图片,若使用<img>略微有些麻烦,iconfont是一个不错的选择用起来也相当灵活,但是所需要步骤较为 ...

  8. CSS伪元素的基本使用

    CSS伪元素的基本使用 上一篇文章介绍了很多个伪类的使用,这篇来说一下伪元素. 伪元素之所以称为"伪",主要是因为它不是真正网页里的元素,但是标线行为又跟真正网页元素一样,也可以对 ...

  9. css 伪元素和浮动

    展示为行内元素 inline-block <style>div {/* 浏览器解析行内块或行内标签的时候, 如果标签换行书写会产生一个空格的距离, 展示为行内元素 */display: i ...

最新文章

  1. 博主谈:聊聊我们说的网站优化
  2. 数学建模题目及论文_数学与运用数学专业论文题目帮助
  3. 第16讲:ODBCJDBC简介
  4. VTK:InfoVis之PKMeansClustering
  5. 程序随笔——C++实现的一个线程池
  6. css3新增了哪三种边框效果,怎么在CSS3中实现一个边框效果
  7. HBase 学习(三) JavaAPI的使用
  8. 【leetcode】726. Number of Atoms
  9. python 生成器装饰器_对Python生成器、装饰器、递归的使用详解
  10. Eigen教程(7)之归约、迭代器和广播
  11. c++数组排序_为什么?为什么?Java处理排序后的数组比没有排序的快?想过没有?
  12. Qt组态软件设计文章导航
  13. Java高级工程师学习要求
  14. 如何在IDEA上创建一个JSP项目【亲测有效】
  15. botley编程机器人测评_好物测评:五岁小孩都能上手的智能编程机器人有多好玩?动手又动脑!...
  16. Hackintosh黑苹果i7-8700+华硕B360MTUFGAME_S+RX5700最终版EFI
  17. NSCalendar 日历类
  18. vue输入空格符 以及空字符串在页面不显示或者只显示一个的问题
  19. HDLbits练习答案(完) 只有你一个success啊
  20. 【数字IC/FPGA】门控时钟

热门文章

  1. 【报告分享】 网易知萌:2020酒行业睿享生活消费趋势报告(附下载)
  2. pythonfor三角函数_Python入门之三角函数全解【收藏】
  3. shell脚本—case用法
  4. css3条纹边框效果
  5. Win10 无法启动print spooler服务 报错1068
  6. 青岛拓谱,一些人一些事
  7. 认识一下 RabbitMQ
  8. Gym报错 The observation returned by the `reset()` method is not contained with the .......
  9. CSS中的浮动float
  10. 地图web开发技术选型