如何从元素中获取应用的样式,不包括默认的用户代理样式

Gyu*_*Fox 7 html javascript css

如何在JavaScript中检索已应用于元素的样式,不包括默认的用户代理样式(仅限内联+样式表样式).

基本上,您可以在您最喜欢的开发人员工具的Computed选项卡中看到所有用户样式:

Edge的开发人员工具中显示的用户样式

没有框架,IE8 +,Edge,Chrome和Firefox.

我希望答案是getComputedStyle减去getDefaultComputedStyle的结果,但是以跨浏览器的方式.看到所有开发人员工具都能够做到这一点,必须有一个解决方案:)

er-*_*han 7

有一个名为'styleSheets'的文档的只读属性.

var styleSheetList = document.styleSheets;
Run Code Online (Sandbox Code Playgroud)

https://developer.mozilla.org/en-US/docs/Web/API/Document/styleSheets

通过使用此功能,您可以访问作者应用的所有样式.

这里有一个类似的问题但不重复,在这里:

是否可以使用Javascript检查样式标记内是否定义了某些CSS属性?

您可以使用我刚才提到的问题的接受答案,从元素中获取应用的样式,不包括默认的用户代理样式.

那个答案没有提供元素自己的style属性内容,所以我对代码进行了一些改进:

var proto = Element.prototype;
var slice = Function.call.bind(Array.prototype.slice);
var matches = Function.call.bind(proto.matchesSelector || 
                proto.mozMatchesSelector || proto.webkitMatchesSelector ||
                proto.msMatchesSelector || proto.oMatchesSelector);

// Returns true if a DOM Element matches a cssRule
var elementMatchCSSRule = function(element, cssRule) {
  return matches(element, cssRule.selectorText);
};

// Returns true if a property is defined in a cssRule
var propertyInCSSRule = function(prop, cssRule) {
  return prop in cssRule.style && cssRule.style[prop] !== "";
};

// Here we get the cssRules across all the stylesheets in one array
var cssRules = slice(document.styleSheets).reduce(function(rules, styleSheet) {
  return rules.concat(slice(styleSheet.cssRules));
}, []);




var getAppliedCss = function(elm) {
	// get only the css rules that matches that element
	var elementRules = cssRules.filter(elementMatchCSSRule.bind(null, elm));
	var rules =[];
	if(elementRules.length) {
		for(i = 0; i < elementRules.length; i++) {
			var e = elementRules[i];
			rules.push({
				order:i,
				text:e.cssText
			})
		}		
	}
	
	if(elm.getAttribute('style')) {
		rules.push({
				order:elementRules.length,
				text:elm.getAttribute('style')
			})
	}
	return rules;
}







function showStyle(){
var styleSheetList = document.styleSheets;
// get a reference to an element, then...
var div1 = document.getElementById("div1");

var rules = getAppliedCss(div1);

var str = '';
for(i = 0; i < rules.length; i++) {
			var r = rules[i];
			str += '<br/>Style Order: ' + r.order + ' | Style Text: ' + r.text; 
		}		
		
	document.getElementById("p1").innerHTML = str;	

}
Run Code Online (Sandbox Code Playgroud)
#div1 {
float:left;
width:100px;
}

div {
text-align:center;
}
Run Code Online (Sandbox Code Playgroud)
<div id="div1" style="font-size:14px;">
	Lorem ipsum 
	</div>
<br/>
<br/>
<a href="javascript:;" onclick="showStyle()"> Show me the style. </a>
	<p id="p1"><p>
Run Code Online (Sandbox Code Playgroud)


Jus*_*ent 5

所有开发人员工具都可以作弊,因为它们可以访问内置浏览器所应用的默认规则。

我认为以下方法可能有效。

  1. 构造一个与我们感兴趣的类型完全相同的元素(例如 adiv或)。p
  2. 将此元素附加到页面上的某个位置,以便仅应用默认的浏览器规则。我们可以通过将其放入iframe.
    例如,如果您确定没有针对任何p元素的规则,则附加到正文可能会更有效。
  3. 检查样式差异并仅报告不同的值。
  4. 清理临时元素。

它在实践中似乎运作得相当好。我只在 Firefox 和 Chrome 中测试了这一点,但我认为它也应该在其他浏览器中工作 - 除了我使用for...infor...of的事实,但人们可以轻松重写它。请注意,不仅报告您指定的属性,还会报告一些受您指定的属性影响的属性。例如,边框颜色根据设计与文本颜色匹配,因此即使您仅设置 ,也会报告为不同的颜色color: white

总而言之,我采用了您在评论中发布的示例,并向getNonDefaultStyles其中添加了一个功能,我认为该功能可以满足您的需求。当然可以修改它来缓存div元素的默认样式,从而在重复调用中更加有效(因为修改 DOM 的成本很高),但它显示了要点。

下面的代码片段展示了如何实现将元素附加到主体的版本。由于 StackOverflow 的限制,无法iframe在代码片段中显示版本。在JSFiddle上是可能的。下面的代码片段也可以在Fiddle中找到。

var textarea = document.getElementById("textarea"),
    paragraph = document.getElementById("paragraph");

/**
 * Computes applied styles, assuming no rules targeting a specific element.
 */
function getNonDefaultStyles(el) {
  var styles = {},
    computed = window.getComputedStyle(el),
    notTargetedContainer = document.createElement('div'),
    elVanilla = document.createElement(el.tagName);
  document.body.appendChild(notTargetedContainer);
  notTargetedContainer.appendChild(elVanilla);
  var vanilla = window.getComputedStyle(elVanilla);
  for (let key of computed) {
    if (vanilla[key] !== computed[key]) {
      styles[key] = computed[key];
    }
  }
  document.body.removeChild(notTargetedContainer);
  return styles;
}

var paragraphStyles = getNonDefaultStyles(paragraph);
for (let style in paragraphStyles) {
  textarea.value += style + ": " + paragraphStyles[style] + "\n";
}
Run Code Online (Sandbox Code Playgroud)
#paragraph {
  background: red;
}

textarea {
  width: 300px;
  height: 400px;
}
Run Code Online (Sandbox Code Playgroud)
<p id="paragraph" style="color: white">
  I am a DIV
</p>

<p>
  User styles:
</p>
<textarea id="textarea"></textarea>
Run Code Online (Sandbox Code Playgroud)