如何使用CSS规则设置元素CSS属性(例如宽度/高度),无论以何种单位设置(例如,百分比/ em / px)? (在谷歌浏览器中,最好是无框架的)。
使用getComputedStyle
以像素为单位返回当前值,jQuery中的css()
也是如此。
例如:
<div class="b">first</div>
<div id="a" class="a">second</div>
<style>
div { width: 100px; }
x, div#a { width: 50%; }
.a { width: 75%; }
</style>
在迭代本示例中的所有div
元素时,我希望第二个div
的宽度为50%
(第一个为100px
)。
Chrome元素检查器可以显示设置的CSS属性值,因此应该可以在Chrome中显示。
不完全重复,因为在接受的答案中有一个简单的hack,无论设置何种宽度,都会产生百分比宽度。其余的你必须知道用于制定活动规则的选择器吗?怎么会知道呢?
答案 0 :(得分:21)
它不像调用WebKits getMatchedCSSRules()
那么简单,它确实按优先级顺序返回匹配的规则(虽然我在文档中没有看到这个顺序),但是顺序没有考虑到属性重要的优先级,不包括元素样式。所以我最终得到了这个功能:
function getMatchedStyle(elem, property){
// element property has highest priority
var val = elem.style.getPropertyValue(property);
// if it's important, we are done
if(elem.style.getPropertyPriority(property))
return val;
// get matched rules
var rules = getMatchedCSSRules(elem);
// iterate the rules backwards
// rules are ordered by priority, highest last
for(var i = rules.length; i --> 0;){
var r = rules[i];
var important = r.style.getPropertyPriority(property);
// if set, only reset if important
if(val == null || important){
val = r.style.getPropertyValue(property);
// done if important
if(important)
break;
}
}
return val;
}
给出以下代码和样式规则:
<div class="b">div 1</div>
<div id="a" class="a d2">div 2</div>
<div id="b" class="b d3" style="width: 333px;">div 3</div>
<div id="c" class="c d4" style="width: 44em;">div 4</div>
<style>
div { width: 100px; }
.d3 { width: auto !important; }
div#b { width: 80%; }
div#c.c { width: 444px; }
x, div.a { width: 50%; }
.a { width: 75%; }
</style>
这个JS代码
var d = document.querySelectorAll('div');
for(var i = 0; i < d.length; ++i){
console.log("div " + (i+1) + ": " + getMatchedStyle(d[i], 'width'));
}
为div
s提供以下宽度:
div 1: 100px
div 2: 50%
div 3: auto
div 4: 44em
答案 1 :(得分:5)
显然没有针对此
的DOM APIhttps://developer.mozilla.org/en/DOM/window.getComputedStyle#Notes
编辑:oops,刚刚意识到这是标记为Google Chrome尝试window.getMatchedCSSRules()
答案 2 :(得分:3)
有一个较新的重复帖子,答案很清楚here。答案是针对jQuery的,但它很容易实现in pure js。
function getDefaultStyle(element, prop) {
var parent = element.parentNode,
computedStyle = getComputedStyle(element),
value;
parent.style.display = 'none';
value = computedStyle.getPropertyValue(prop);
parent.style.removeProperty('display');
return value;
}
答案 3 :(得分:3)
大家好消息!在w3c草案中似乎有CSS Typed OM。
快速阅读本文档,似乎这个可能是规范的目标是简化javascript对CSSOM值的访问。
这对我们来说真正重要的部分是我们将有一个CSSUnitValue API,它能够将CSS值解析为表单的对象
{
value: 100,
unit: "percent", // | "px" | "em" ...
type: "percent" // | "length"
}
并在Element接口中添加computedStyleMap()
方法,我们将从中获取实际应用于元素的值。
截至今天,only Chrome implements it(自66年起)。
(() => {
if (!Element.prototype.computedStyleMap) {
console.error("Your browser doesn't support CSS Typed OM");
return;
}
document.querySelectorAll('.test')
.forEach((elem) => {
let styleMap = elem.computedStyleMap();
const unitvalue = styleMap.get('width');
console.log(elem, {
type: unitvalue.type(),
unit: unitvalue.unit,
value: unitvalue.value
});
});
/* outputs
<div class="b test">first</div> {
"type": {
"length": 1
},
"unit": "px",
"value": 100
}
<div id="a" class="a test">second</div> {
"type": {
"percent": 1
},
"unit": "percent",
"value": 50
}
*/
})();
&#13;
div.test { width: 100px; }
x,div#a { width: 50%; }
.a { width: 75%; }
&#13;
<div class="b test">first</div>
<div id="a" class="a test">second</div>
&#13;
答案 4 :(得分:2)
我很惊讶没有看到这个答案,因此:您可以自己浏览样式表并获取有关与元素匹配的规则的信息。
这是一个示例的粗略草图,使用specificity
库来计算选择器特异性。 getComputedStyle
会告诉您这些尺寸(以像素为单位),而不是原始单位。
function applyStyles(target, style, specificity, appliedSpecs) {
// Loop through its styles
for (let [key, value] of Object.entries(style)) {
// Skip the numerically-indexed ones giving us property names
if (/^\d+$/.test(key)) {
continue;
}
if (value !== "") {
// Non-blank style. If it has !important, add to specificity.
let thisSpec = specificity;
if (style.getPropertyPriority(key) === "important") {
// Important rule, so bump the first value (which will currently be 0
// for a stylesheet style and 1 for an inline style
thisSpec = [specificity[0] + 1, ...specificity.slice(1)];
}
// Non-blank style, do we have a style already and if so, with
// what specificity?
const currentSpec = appliedSpecs[key];
if (!currentSpec || SPECIFICITY.compare(thisSpec, currentSpec) >= 0) {
// Either we didn't already have this style or this new one
// has the same or higher specificity and overrides it.
target[key] = value;
appliedSpecs[key] = thisSpec;
}
}
}
}
function getDeclaredStyle(el) {
// An object to fill in with styles
const style = {};
// An object to remember the specificity of the selector that set a style
const appliedSpecs = {};
// Loop through the sheets in order
for (const sheet of Array.from(el.ownerDocument.styleSheets)) {
// Loop through the rules
const rules = sheet.cssRules || sheet.rules;
if (rules) {
for (const rule of Array.from(rules)) {
const {selectorText} = rule;
if (selectorText && el.matches(selectorText)) {
// This rule matches our element
if (rule.style) {
// Get the specificity of this rule
const specificity = SPECIFICITY.calculate(selectorText)[0].specificityArray;
// Apply these styles
applyStyles(style, rule.style, specificity, appliedSpecs);
}
}
}
}
}
// Apply inline styles
applyStyles(style, el.style, [0, 255, 255, 255], appliedSpecs);
return style;
}
// Get the element
const el = document.querySelector("div.a.b");
// Get its declared style
const style = getDeclaredStyle(el);
// Height is 3em because .a.b is more specific than .a
console.log("height: " + style.height); // "3em"
// Width is 5em because of the !important flag; it overrides the inline style rule
console.log("width: " + style.width); // "5em"
// Border width is 1em because the rule is later than the other rules
console.log("line-height: " + style.lineHeight); // "1.2"
// Color is blue because the inline style rule is !important
console.log("color: " + style.color); // "blue"
// Compare with results of `getComputedStyle`:
const computed = getComputedStyle(el);
console.log("computed height: " + computed.height);
console.log("computed width: " + computed.width);
console.log("computed line-height: " + computed.lineHeight);
console.log("completed color: " + computed.color);
.a {
width: 1em;
height: 1em;
width: 5em !important;
color: red !important;
line-height: 1.0;
color: yellow !important;
}
.a.b {
height: 3em;
}
.a {
height: 2em;
width: 4em;
line-height: 1.2;
}
.as-console-wrapper {
max-height: 100% !important;
}
<script src="//unpkg.com/specificity@0.4.1/dist/specificity.js"></script>
<div class="a b" style="width: 4em; color: blue !important">x</div>
再次,这只是一个草图,但它应该以正确的方式引导您...
这是ES5版本:
// Get the element
var el = document.querySelector("div.a.b");
// An object to fill in with styles
var style = {};
// An object to remember the specificity of the selector that set a style
var specificity = {};
// Loop through the sheets in order
for (var sheetIndex = 0; sheetIndex < document.styleSheets.length; ++sheetIndex) {
var sheet = document.styleSheets[sheetIndex];
// Loop through the rules
var rules = sheet.cssRules || sheet.rules;
if (rules) {
for (var ruleIndex = 0; ruleIndex < rules.length; ++ruleIndex) {
var rule = rules[ruleIndex];
var selectorText = rule.selectorText;
if (selectorText && el.matches(selectorText)) {
// This rule matches our element
if (rule.style) {
// Get the specificity of this rule
var spec = SPECIFICITY.calculate(selectorText)[0].specificityArray;
// Loop through its styles
for (var key in rule.style) {
// Skip inherited ones and the numerically-indexed ones giving us property names
if (/^\d+$/.test(key) || !rule.style.hasOwnProperty(key)) {
continue;
}
var value = rule.style[key];
if (value !== "") {
// Non-blank style. If it has !important, add to specificity
var thisSpec = spec;
if (rule.style.getPropertyPriority(key) === "important") {
thisSpec = spec.slice();
thisSpec[0] = 1;
}
// Non-blank style, do we have a style already and if so, with
// what specificity?
var currentSpec = specificity[key];
if (!currentSpec || SPECIFICITY.compare(thisSpec, currentSpec) >= 0) {
// Either we didn't already have this style or this new one
// has the same or higher specificity and overrides it
style[key] = value;
specificity[key] = thisSpec;
}
}
}
}
}
}
}
}
// Height is 3em because .a.b is more specific than .a
console.log("height: " + style.height); // "3em"
// Width is 5em because of the !important flag
console.log("width: " + style.width); // "5em"
// Border width is 1em because the rule is later than the other rules
console.log("line-height: " + style.lineHeight); // "1.2"
// Compare with results of `getComputedStyle`:
var computed = getComputedStyle(el);
console.log("computed height: " + computed.height);
console.log("computed width: " + computed.width);
console.log("computed line-height: " + computed.lineHeight);
.a {
height: 1em;
width: 5em !important;
line-height: 1.0;
}
.a.b {
height: 3em;
}
.a {
height: 2em;
width: 4em;
line-height: 1.2;
}
<script src="//unpkg.com/specificity@0.4.1/dist/specificity.js"></script>
<div class="a b"></div>
注意:上述不做的两件事是:
从祖先元素继承的句柄样式。如果您只对知道继承的单个属性感兴趣,则可以使用上面的属性,如果没有设置该属性,请对父属性重复,等等。或者可以扩展该属性以基于list of properties(说明它们是否被继承)和rules of inheritance(小心允许inherit
,initial
,unset
和{{ 1}}关键字以及revert
关键字)。
媒体查询。上面的代码段仅适用于所有带有样式的规则。它应该检查CSSMediaRules
,查看它们是否与当前媒体匹配(可能使用matchMedia
),如果匹配,请进入其all
并应用它们。也许不是那么难。