如何判断HTML元素是否有伪元素?
How to determine if HTML element has pseudo element?
有没有办法确定给定的 HTML 元素应用了伪元素 (::before
/ ::after
) 而无需调用
window.getComputedStyle(element, ":before/:after");
已编辑:答案是否
getComputedStyle 的问题在于性能。我需要验证页面上的每个元素是否具有伪元素——这就是性能非常关键的原因。
我尝试从 document.styleSheets 访问 cssRules 以查找末尾带有 ::before 或 ::after 的选择器,删除它并找到与其余选择器匹配的元素,但此解决方案有其自身的问题:
- 无法访问来自不同域的样式表
- 可能有数以千计的 cssRules 需要检查(同样是性能)
我还尝试比较有无伪元素时元素的大小和偏移量,但没有任何效果。即使没有准确的方法,我也很乐意找到一种方法,将要检查的元素数量至少减少 30%。
当我确定该元素具有伪元素时,我终于可以调用 getComputedStyle 来调查伪元素样式并更改它。这部分完美运行。
已编辑:我无法控制源页面。页面样式可以从不同域动态上传。假设我的代码是内容脚本或库,例如 必须将所有伪元素前景更改为根据该伪元素的其他 CSS 属性计算的某种颜色。
主要问题是更改是基于其他 CSS 属性的,如果不实际检索伪元素的计算样式并计算更改,就不能为所有伪元素设置相同的样式。
例如你有 youtube.com 页面,你需要找到所有伪元素和
- 如果这个伪元素有背景图片然后缩放元素
- 如果此伪元素只有文本,则将其颜色更改为红色
- 等...
我认为 getComputedStyle()
是了解元素是否附加了伪元素的唯一可靠方法。
但是由于无法通过 DOM 方法对其进行编辑,这意味着您必须在文档中附加一条新规则。
所以一个简单的解决方案,如果如上次编辑所述,您将对 all 伪元素应用相同的规则,则使用通配符 *
选择器:
*:before,*:after{ /*your rules*/ }
var style = document.createElement('style');
style.innerHTML = `*:before,*:after{
color: green !important;
}`;
setTimeout(function() {
document.head.appendChild(style);
}, 1500);
div:before {
content: 'hello';
color: blue;
}
div:after {
content: 'world';
color: red;
}
<div></div>
究竟是什么导致您现有的解决方案出现问题?
这种遍历元素的方法:
var allElements = document.getElementsByTagName("*");
for (var i = allElements.length; i--;) {
//var usedStyle = window.getComputedStyle(allElements[i], ":before/:after");
...
}
大约是每 1 毫秒 千 个元素。
并且 getComputedStyle
的调用不应太慢,因为它获取调用时已经计算的数据(在呈现的文档上)。
所以这一切都应该足够快。是的,原则上是 O(N)
任务,但得到 运行 一次,对吧?
有没有办法确定给定的 HTML 元素应用了伪元素 (::before
/ ::after
) 而无需调用
window.getComputedStyle(element, ":before/:after");
已编辑:答案是否
getComputedStyle 的问题在于性能。我需要验证页面上的每个元素是否具有伪元素——这就是性能非常关键的原因。 我尝试从 document.styleSheets 访问 cssRules 以查找末尾带有 ::before 或 ::after 的选择器,删除它并找到与其余选择器匹配的元素,但此解决方案有其自身的问题:
- 无法访问来自不同域的样式表
- 可能有数以千计的 cssRules 需要检查(同样是性能)
我还尝试比较有无伪元素时元素的大小和偏移量,但没有任何效果。即使没有准确的方法,我也很乐意找到一种方法,将要检查的元素数量至少减少 30%。
当我确定该元素具有伪元素时,我终于可以调用 getComputedStyle 来调查伪元素样式并更改它。这部分完美运行。
已编辑:我无法控制源页面。页面样式可以从不同域动态上传。假设我的代码是内容脚本或库,例如 必须将所有伪元素前景更改为根据该伪元素的其他 CSS 属性计算的某种颜色。
主要问题是更改是基于其他 CSS 属性的,如果不实际检索伪元素的计算样式并计算更改,就不能为所有伪元素设置相同的样式。
例如你有 youtube.com 页面,你需要找到所有伪元素和
- 如果这个伪元素有背景图片然后缩放元素
- 如果此伪元素只有文本,则将其颜色更改为红色
- 等...
我认为 getComputedStyle()
是了解元素是否附加了伪元素的唯一可靠方法。
但是由于无法通过 DOM 方法对其进行编辑,这意味着您必须在文档中附加一条新规则。
所以一个简单的解决方案,如果如上次编辑所述,您将对 all 伪元素应用相同的规则,则使用通配符 *
选择器:
*:before,*:after{ /*your rules*/ }
var style = document.createElement('style');
style.innerHTML = `*:before,*:after{
color: green !important;
}`;
setTimeout(function() {
document.head.appendChild(style);
}, 1500);
div:before {
content: 'hello';
color: blue;
}
div:after {
content: 'world';
color: red;
}
<div></div>
究竟是什么导致您现有的解决方案出现问题?
这种遍历元素的方法:
var allElements = document.getElementsByTagName("*");
for (var i = allElements.length; i--;) {
//var usedStyle = window.getComputedStyle(allElements[i], ":before/:after");
...
}
大约是每 1 毫秒 千 个元素。
并且 getComputedStyle
的调用不应太慢,因为它获取调用时已经计算的数据(在呈现的文档上)。
所以这一切都应该足够快。是的,原则上是 O(N)
任务,但得到 运行 一次,对吧?