[英]Get element CSS property (width/height) value as it was set (in percent/em/px/etc)
如何獲得元素 CSS 屬性(例如寬度/高度),因為它是用 CSS 規則設置的,無論它設置的是什么單位(例如百分比/em/px)? (在 Google Chrome 中,最好是無框架的)。
使用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 中應該是可能的。
不是鏈接問題的完全重復,因為在那里接受的答案有一個簡單的技巧,無論設置什么樣的寬度,都會產生一個百分比寬度。 至於其余的,您必須知道用於制定活動規則的選擇器嗎? 怎么會知道呢?
它並不像調用 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
提供以下寬度:
div 1: 100px
div 2: 50%
div 3: auto
div 4: 44em
(在 jsFiddle )
大家好消息! 在他的 w3c 草案中似乎有一個CSS Typed OM 。
快速閱讀本文檔,似乎這個可能即將成為規范的目標是簡化從 javascript 訪問 CSSOM 值的過程。
對我們來說真正重要的部分是我們將有一個CSSUnitValue API,它將能夠將 CSS 值解析為表單的對象
{
value: 100,
unit: "percent", // | "px" | "em" ...
type: "percent" // | "length"
}
並在 Element 接口中添加一個computedStyleMap()
方法,我們將能夠從中獲取實際應用於我們元素的值。
截至今天,只有 Chrome 實現了它(從 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 } */ })();
div.test { width: 100px; } x,div#a { width: 50%; } .a { width: 75%; }
<div class="b test">first</div> <div id="a" class="a test">second</div>
顯然沒有 DOM API 用於此
https://developer.mozilla.org/en/DOM/window.getComputedStyle#Notes
編輯:哎呀,剛剛意識到這是為谷歌瀏覽器標記的
試試 window.getMatchedCSSRules()
有一個較新的重復帖子,這里有一個很好的答案。 該答案適用於 jQuery,但在純 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;
}
我很驚訝沒有看到這個答案,所以:您可以通過自己瀏覽樣式表並獲取有關與元素匹配的規則的信息來到達那里。
這是一個示例的粗略草圖,使用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.ab"); // Get its declared style const style = getDeclaredStyle(el); // Height is 3em because .ab 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; } .ab { 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="ab" style="width: 4em; color: blue !important">x</div>
再說一次,這只是一個草圖,但它應該引導你正確的方式......
這是一個 ES5 版本:
// Get the element var el = document.querySelector("div.ab"); // 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 .ab 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; } .ab { 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="ab"></div>
注意:上面沒有做的兩件大事是:
處理從祖先元素繼承的樣式。 如果您只對您知道是繼承的單個屬性感興趣,您可以使用上面的,如果它沒有設置屬性,則重復父級等。或者可以擴展它以應用基於的繼承表明它們是否被繼承的屬性列表以及繼承規則(注意允許使用inherit
、 initial
、 unset
和revert
關鍵字,以及all
關鍵字)。
媒體查詢。 上面的代碼段只應用所有帶有樣式的規則。 它應該檢查CSSMediaRules
,查看它們是否與當前媒體匹配(可能使用matchMedia
),如果匹配,則進入他們的cssRules
並應用它們。 可能沒有那么難。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.