JS操作CSS伪元素
参考链接:
- 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伪元素相关推荐
- [JS 分析] 汽_车_之_家 JS 生成 CSS 伪元素 hs_kw44_configUS::before
0.参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements https://developer.mozilla.org/ ...
- jquery改变选中对象的css,使用jQuery选择和操作CSS伪元素,例如:: before和:: after
DIEA 您认为这将是一个简单的问题,jQuery可以做的其他事情.不幸的是,问题归结为一个技术问题:css:after和:之前规则不是DOM的一部分,因此不能使用jQuery的DOM方法进行更改.有 ...
- 如何修改css伪元素的样式
首先说一下变成思想,众所周知,css伪元素是不可以修改的,首先你查找他的元素就很困难,不知道怎么查找的可以看一下我的另一篇原生js查看css伪元素属性,那么我们应该怎么修改呢 . 其实换一种思维事情就 ...
- html 的css骚操作,意想不到的 CSS 伪元素 before/after 各种骚操作 - 文章教程
CSS 伪元素 before/after 我们经常用到,常见的就是画个三角形.绘画背景阴影等,这篇文章将给大家分享还有很多有趣的操作,比如画线画图标等. 画细线 普通的 border 最小高度为1px ...
- CSS伪元素::before,::after
W3C的解释用一句话概括:单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素中. css伪元素,之所以被称为伪元素,是因为他们不是真正的页面元素,html页面中没有对应的元素,但是其所有用 ...
- JavaScript 如何使用JS操作CSS
家人们,新的一天新的知识点,我们要开启新的课程啦,今天带大家学习如何使用JS操作css,大家有不懂得可以私信我,或者在下方评论噢,现在就让我带你们进入知识的海洋中. 一.什么是css? Cascad ...
- 【伪类与伪元素】用CSS伪元素(以:before为例)插入图片
[伪类与伪元素]用CSS伪元素(以:before为例)插入图片 对于一些小图标类型的图片,若使用<img>略微有些麻烦,iconfont是一个不错的选择用起来也相当灵活,但是所需要步骤较为 ...
- CSS伪元素的基本使用
CSS伪元素的基本使用 上一篇文章介绍了很多个伪类的使用,这篇来说一下伪元素. 伪元素之所以称为"伪",主要是因为它不是真正网页里的元素,但是标线行为又跟真正网页元素一样,也可以对 ...
- css 伪元素和浮动
展示为行内元素 inline-block <style>div {/* 浏览器解析行内块或行内标签的时候, 如果标签换行书写会产生一个空格的距离, 展示为行内元素 */display: i ...
最新文章
- 博主谈:聊聊我们说的网站优化
- 数学建模题目及论文_数学与运用数学专业论文题目帮助
- 第16讲:ODBCJDBC简介
- VTK:InfoVis之PKMeansClustering
- 程序随笔——C++实现的一个线程池
- css3新增了哪三种边框效果,怎么在CSS3中实现一个边框效果
- HBase 学习(三) JavaAPI的使用
- 【leetcode】726. Number of Atoms
- python 生成器装饰器_对Python生成器、装饰器、递归的使用详解
- Eigen教程(7)之归约、迭代器和广播
- c++数组排序_为什么?为什么?Java处理排序后的数组比没有排序的快?想过没有?
- Qt组态软件设计文章导航
- Java高级工程师学习要求
- 如何在IDEA上创建一个JSP项目【亲测有效】
- botley编程机器人测评_好物测评:五岁小孩都能上手的智能编程机器人有多好玩?动手又动脑!...
- Hackintosh黑苹果i7-8700+华硕B360MTUFGAME_S+RX5700最终版EFI
- NSCalendar 日历类
- vue输入空格符 以及空字符串在页面不显示或者只显示一个的问题
- HDLbits练习答案(完) 只有你一个success啊
- 【数字IC/FPGA】门控时钟
热门文章
- 【报告分享】 网易知萌:2020酒行业睿享生活消费趋势报告(附下载)
- pythonfor三角函数_Python入门之三角函数全解【收藏】
- shell脚本—case用法
- css3条纹边框效果
- Win10 无法启动print spooler服务 报错1068
- 青岛拓谱,一些人一些事
- 认识一下 RabbitMQ
- Gym报错 The observation returned by the `reset()` method is not contained with the .......
- CSS中的浮动float
- 地图web开发技术选型