Javascript 查找应用于元素的所有CSS规则
许多工具/API提供了选择特定类或ID的元素的方法。还可以检查浏览器加载的原始样式表 但是,对于要呈现元素的浏览器,他们将编译所有CSS规则(可能来自不同的样式表文件)并将其应用于元素。这是您在Firebug或WebKit Inspector(元素的完整CSS继承树)中看到的 如何在不需要额外的浏览器插件的情况下在纯JavaScript中重现此功能 也许一个例子可以为我寻找的东西提供一些澄清:Javascript 查找应用于元素的所有CSS规则,javascript,css,Javascript,Css,许多工具/API提供了选择特定类或ID的元素的方法。还可以检查浏览器加载的原始样式表 但是,对于要呈现元素的浏览器,他们将编译所有CSS规则(可能来自不同的样式表文件)并将其应用于元素。这是您在Firebug或WebKit Inspector(元素的完整CSS继承树)中看到的 如何在不需要额外的浏览器插件的情况下在纯JavaScript中重现此功能 也许一个例子可以为我寻找的东西提供一些澄清: <style type="text/css"> p { color :red; }
<style type="text/css">
p { color :red; }
#description { font-size: 20px; }
</style>
<p id="description">Lorem ipsum</p>
p{颜色:红色;}
#说明{字体大小:20px;}
Lorem ipsum
这里p#description元素应用了两个CSS规则:红色和20px的字体大小
我想找到这些计算出的CSS规则的来源(颜色来自p规则等等)。编辑:这个答案现在已被弃用,并被删除。离开历史背景。事实上,bug报告链接回这个问题,寻找使用这个问题的替代解决方案
似乎在又一个小时的研究之后,我终于回答了自己的问题 就这么简单:
window.getMatchedCSSRules(document.getElementById("description"))
(适用于WebKit/Chrome,可能还有其他版本)看看这个库,它满足了用户的要求:
它适用于所有现代浏览器,可以追溯到IE6,可以为您提供规则和属性集合,比如Firebug(事实上它比Firebug更精确),还可以计算任何规则的相对或绝对特异性。唯一需要注意的是,尽管它了解静态媒体类型,但它不了解媒体查询。由于这个问题目前没有一个轻量级(非库)跨浏览器兼容的答案,我将尝试提供一个:
function css(el) {
var sheets = document.styleSheets, ret = [];
el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector
|| el.msMatchesSelector || el.oMatchesSelector;
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
if (el.matches(rules[r].selectorText)) {
ret.push(rules[r].cssText);
}
}
}
return ret;
}
JSFiddle:
调用css(document.getElementById('elementId'))
将返回一个数组,其中每个css规则对应一个与传递的元素匹配的元素。
如果您想了解有关每个规则的更多具体信息,请查看文档。以下是s.B.答案的一个版本,它还将在匹配媒体查询中返回匹配规则。我已经删除了
*.rules | |*.cssRules
合并和.matches
实现查找器;添加一个多边形填充,或者在需要时将这些线条添加回
此版本还返回CSSStyleRule
对象,而不是规则文本。我认为这更有用一点,因为通过这种方式可以更容易地以编程方式探索规则的细节
咖啡:
getMatchedCSSRules=(元素)->
sheets=document.styleSheets
匹配=[]
loopRules=(规则)->
规则中的规则
CSSMediaRule的if规则实例
如果window.matchMedia(rule.conditionText).matches
loopRules rule.cssRules
else if CSSStyleRule的规则实例
如果element.matches rule.selectorText
匹配推送规则
返回
loopRules sheet.cssRules用于图纸中的图纸
返回匹配
JS:
函数getMatchedCSSRules(元素){
变量i,len,matching=[],sheets=document.styleSheets;
函数循环规则(规则){
变量i,len,规则;
for(i=0,len=rules.length;i
2017年4月12日短版
挑战者号出现了
var getMatchedCSSRules=(el,css=el.ownerDocument.styleSheets)=>
[].concat(…[…css].map(s=>[…s.cssRules | |[]])/*1*/
.filter(r=>el.matches(r.selectorText));/*2 */
行/*1*/
构建所有规则的平面数组。行
/*2*/
丢弃不匹配的规则
基于同一页上的@S.B
例1
例2
var getMatchedCSSRules=(el,css=el.ownerDocument.styleSheets)=>
[].concat(…[…css].map(s=>[…s.cssRules | |[]))
.filter(r=>el.matches(r.selectorText));
功能开始(大,显示){
var r=getMatchedCSSRules(大);
打印信息:
var f=(dd,rr,ee=“\n”)=>dd+rr.cssText.slice(0,50)+ee;
show.value+=“--------------规则:--------------\n”;
show.value+=f(“规则1:,r[0]);
show.value+=f(“规则2:,r[1]);
show.value+=f(“内联:”,big.style);
show.value+=f(“计算:”,getComputedStyle(大),“(…)\n”);
show.value+=“-----------样式元素(HTML):----------\n”;
show.value+=r[0].parentStyleSheet.ownerNode.outerHTML;
}
Go(…document.queryselectoral(“#big,#show”)代码>
.red{color:red;}
#大{font size:20px;}
Lorem ipsum
var GetMatchedCSSRules=(elem,css=document.styleSheets)=>Array.from(css)
.map(s=>Array.from(s.cssRules).filter(r=>elem.matches(r.selectorText)))
.减少((a,b)=>a.concat(b));
功能Go(段落,打印){
var规则=GetMatchedCSSRules(第段);
打印信息:
print.value+=“规则1:+规则[0].cssText+“\n”;
print.value+=“规则2:”+规则[1].cssText+“\n\n”;
print.value+=规则[0]。parentStyleSheet.ownerNode.outerHTML;
}
Go(document.getElementById(“说明”)、document.getElementById(“打印”)代码>
p{color:red;}
#说明{字体大小:20px;}
Lorem ipsum
为了确保IE9+,我编写了一个函数,用于计算请求元素及其子元素的CSS,并在下面的代码段中提供了将其保存到新类名的可能性(如果需要)
/**
* @function getElementStyles
*
* Computes all CSS for requested HTMLElement and its child nodes and applies to dummy class
*
* @param {HTMLElement} element
* @param {string} className (optional)
* @param {string} extras (optional)
* @return {string} CSS Styles
*/
function getElementStyles(element, className, addOnCSS) {
if (element.nodeType !== 1) {
return;
}
var styles = '';
var children = element.getElementsByTagName('*');
className = className || '.' + element.className.replace(/^| /g, '.');
addOnCSS = addOnCSS || '';
styles += className + '{' + (window.getComputedStyle(element, null).cssText + addOnCSS) + '}';
for (var j = 0; j < children.length; j++) {
if (children[j].className) {
var childClassName = '.' + children[j].className.replace(/^| /g, '.');
styles += ' ' + className + '>' + childClassName +
'{' + window.getComputedStyle(children[j], null).cssText + '}';
}
}
return styles;
}
这是我的getMatchedCSSRules/**
* @function getElementStyles
*
* Computes all CSS for requested HTMLElement and its child nodes and applies to dummy class
*
* @param {HTMLElement} element
* @param {string} className (optional)
* @param {string} extras (optional)
* @return {string} CSS Styles
*/
function getElementStyles(element, className, addOnCSS) {
if (element.nodeType !== 1) {
return;
}
var styles = '';
var children = element.getElementsByTagName('*');
className = className || '.' + element.className.replace(/^| /g, '.');
addOnCSS = addOnCSS || '';
styles += className + '{' + (window.getComputedStyle(element, null).cssText + addOnCSS) + '}';
for (var j = 0; j < children.length; j++) {
if (children[j].className) {
var childClassName = '.' + children[j].className.replace(/^| /g, '.');
styles += ' ' + className + '>' + childClassName +
'{' + window.getComputedStyle(children[j], null).cssText + '}';
}
}
return styles;
}
getElementStyles(document.getElementByClassName('.my-class'), '.dummy-class', 'width:100%;opaity:0.5;transform:scale(1.5);');
const getMatchedCSSRules = (el) => {
let rules = [...document.styleSheets]
rules = rules.filter(({ href }) => !href)
rules = rules.map((sheet) => [...(sheet.cssRules || sheet.rules || [])].map((rule) => {
if (rule instanceof CSSStyleRule) {
return [rule]
} else if (rule instanceof CSSMediaRule && window.matchMedia(rule.conditionText)) {
return [...rule.cssRules]
}
return []
}))
rules = rules.reduce((acc, rules) => acc.concat(...rules), [])
rules = rules.filter((rule) => el.matches(rule.selectorText))
rules = rules.map(({ style }) => style)
return rules
}
<html><head>
<title>CSS Test</title>
<style id="style-a">
li {color: #333; font-size: 20px !important;}
li.bb {color: #600; font-size: 10px;}
p {margin: 5px;}
p {margin-bottom: 10px;}
</style>
<script>
window.addEventListener('DOMContentLoaded', async () => {
const selector = 'li';
// const selector = 'li.bb';
const exempleValues = {
'color': ['rgb(0, 0, 0)', 'rgb(255, 255, 255)'],
'font-size': ['10px', '12px'],
};
const delay = (t) => new Promise((k, e) => {setTimeout(k, t)});
for(const element of document.querySelectorAll(selector)) {
const elementCss = document.defaultView.getComputedStyle(element);
for(const sheet of document.styleSheets) {
for(const rule of sheet.cssRules) {
if(rule.selectorText !== selector) {
continue;
}
for(const properyName of rule.style) {
const currentValue = rule.style[properyName];
const priority = rule.style.getPropertyPriority(properyName)
if(!exempleValues[properyName]) {
console.warn('no exemple values for', properyName);
continue;
}
const exempleValue = exempleValues[properyName][exempleValues[properyName][0] === currentValue ? 1 : 0];
rule.style.setProperty(properyName, exempleValue, priority);
await delay(100);
if(exempleValue === elementCss[properyName]) {
console.log(selector, properyName, currentValue, priority || false, true, 'in use', element, sheet.ownerNode);
} else {
console.log(selector, properyName, currentValue, priority || false, false, 'overrided', element);
}
rule.style.setProperty(properyName, currentValue, priority);
await delay(100);
}
}
}
}
}, {once: true});
</script>
</head><body>
<h1>CSS Test</h1>
<p>html-file for testing css</p>
<ul>
<li>AAAA</li>
<li class="bb">BBBB</li>
<li>CCCC</li>
</ul>
</body></html>