检查 css 属性是否应用了 !重要属性

Check if css property has !important attribute applied

本文关键字:属性 应用 css 是否 检查      更新时间:2023-09-26

如果我有这样的风格——

​div#testdiv {position:absolute;top:10px !important;}​

我可以像这样使用 jQuery 查询top值 -

$("#testdiv").css("top");

这将返回值10px .是否可以使用 jQuery 或 JavaScript 来检查 top 属性是否应用了 !important 属性?

首先,这样的解决方案在jQuery中似乎不存在。

提供了许多可用的JavaScript解决方案,使用函数getPropertyPriority()。首先,IE6-IE8不支持此功能(请参阅此处和此处)。其次,如果元素的样式未内声明,则此函数不直接处理元素。因此,在以下情况下,我们将能够获得重要属性:

<div id="testdiv" style="top : 10px !important;">Some div</div>
<script type="text/javascript">
// should show 'important' in the console.
console.log(document.getElementById("testdiv").style.getPropertyPriority('top'));
</script>

但是,如果我们可以在 css 样式表中声明#testdiv样式,我们将得到一个空字符串。此外,CSSStyleDeclaration接口在IE6-8中不可用。当然,这样是没有用的。我们需要一种不同的方法。

我已经将这种方法放入JSFiddle中。我们可以直接从包含在数组document.styleSheets[]中的 css 样式表中读取 !important 属性。(Opera 8 及更低版本不支持此数组)。在Quirksmode中,您可以看到支持哪些方法访问样式表的方法。根据这些信息,我们可以执行以下操作:

  • 对于IE6-8,我们使用styleSheets[].imports来访问导入的样式表(并继续递归地执行此操作,直到我们不再找到任何导入语句),然后基本上styleSheets[].rules为每个样式表将css规则添加到数组中。
  • 对于其他浏览器,我们使用styleSheets[].cssRules来访问导入的规则和 css 规则。我们通过检查导入规则是否实现了 CSSImportRule 接口来检测导入规则,并使用这些规则递归访问导入样式表中的 css 规则。

在这两种情况下,我们仅在规则与 HTML 匹配时才将 css 规则添加到数组中(在您的情况下#testdiv )。这会产生与 HTML 环境匹配的 css 规则数组。这基本上就是webkit浏览器中的getMatchedCSSRules()功能所做的。但是,我们在这里自己写。

基于这些信息,我们编写了hasImportant(htmlNode, property)函数,其中htmlNode是一个HTMLElement(你的testdiv),属性是css属性(在你的例子中是"top")。首先,我们检查 top 属性的内联样式是否具有重要属性。这样可以节省我们查看样式表是否包含此属性的情况。

我们编写一个新的函数isImportant(node, property)它使用我们很好的旧函数node.style.getPropertyPriority(property)。但是,就像我之前在这个答案中提到的:IE6-IE8不支持此功能。我们可以自己编写函数:在IE中,属性node.style.cssText包含声明块文本。我们在此文本块中搜索属性("top"),并检查其值是否包含"!important"。我们可以在使用 getMatchedCSSRules 函数获取的每个 css 规则上重用此函数,方法是遍历与 htmlNode 匹配的所有 css 规则并调用 isImportant 函数。

以上所有内容都可以在下面的代码中找到。这是基本方法,可能应该进一步微调:

  • 某些代码可能会替换为 jQuery
  • 某些代码可能会简化
  • 实现 CSSMediaRule 接口和其他接口的 css 规则可能会导致此代码出现一些问题,应执行错误检查
  • 可能有更简单的方法,但我不知道任何其他方法可以让这个跨浏览器工作。

    var debug = true;
    /**
     * Get the css rules of a stylesheet which apply to the htmlNode. Meaning its class
     * its id and its tag.
     * @param CSSStyleSheet styleSheet
     * @param HTMLElement htmlNode
     */
    function getCssRules(styleSheet, htmlNode) {
        if ( !styleSheet )
            return null;
        var cssRules = new Array();
        if (styleSheet.cssRules) {
            var currentCssRules = styleSheet.cssRules;
            // Import statement are always at the top of the css file.
            for ( var i = 0; i < currentCssRules.length; i++ ) {
                // cssRules all contains the import statements.
                // check if the rule is an import rule.
                if ( isImportRule(currentCssRules[i]) ) {
                    // import the rules from the imported css file.
                    var importCssRules = getCssRules(currentCssRules[i].styleSheet, htmlNode);
                    if ( importCssRules != null ) {
                        // Add the rules from the import css file to the list of css rules.
                        cssRules = addToArray(cssRules, importCssRules, htmlNode);
                    }
                    // Remove the import css rule from the css rules.
                    styleSheet.deleteRule(i);
                }
                else {
                    // We found a rule that is not an CSSImportRule
                    break;
                }
            }
            // After adding the import rules (lower priority than those in the current stylesheet),
            // add the rules in the current stylesheet.
            cssRules = addToArray(cssRules, currentCssRules, htmlNode);
        }
        else if (styleSheet.rules) {
            // IE6-8
            // rules do not contain the import statements.
            var currentCssRules = styleSheet.rules;
            // Handle the imports in a styleSheet file.
            if ( styleSheet.imports ) {
                // IE6-8 use a seperate array which contains the imported css files.
                var imports = styleSheet.imports;
                for ( var i = 0; i < imports.length; i++ ) {
                    var importCssRules = getCssRules(imports[i], htmlNode);
                    if ( importCssRules != null ) {
                        // Add the rules from the import css file to the list of css rules.
                        cssRules = addToArray(cssRules, importCssRules, htmlNode);
                    }
                }
            }
            // After adding the import rules (lower priority than those in the current stylesheet),
            // add the rules in the current stylesheet.
            cssRules = addToArray(cssRules, currentCssRules, htmlNode);
        }
        return cssRules;
    }
    /**
     * Since a list of rules is returned, we cannot use concat. 
     * Just use old good push....
     * @param CSSRuleList cssRules
     * @param CSSRuleList cssRules
     * @param HTMLElement htmlNode
     */
    function addToArray(cssRules, newRules, htmlNode) {
        for ( var i = 0; i < newRules.length; i++ ) {
            if ( htmlNode != undefined && htmlNode != null && isMatchCssRule(htmlNode, newRules[i]) )
                cssRules.push(newRules[i]);
        }
        return cssRules;
    }
    /**
     * Matches a htmlNode to a cssRule. If it matches, return true.
     * @param HTMLElement htmlNode
     * @param CSSRule cssRule
     */
    function isMatchCssRule(htmlNode, cssRule) {
        // Simply use jQuery here to see if there cssRule matches the htmlNode...
        return $(htmlNode).is(cssRule.selectorText);
    }
    /**
     * Verifies if the cssRule implements the interface of type CSSImportRule.
     * @param CSSRule cssRule
     */
    function isImportRule(cssRule) {
        return cssRule.constructor.toString().search("CSSImportRule") != -1;
    }
    /**
     * Webkit browsers contain this function, but other browsers do not (yet).
     * Implement it ourselves...
     *
     * Finds all matching CSS rules for the htmlNode.
     * @param HTMLElement htmlNode
     */
    function getMatchedCSSRules(htmlNode) {
        var cssRules = new Array();
        // Opera 8- don't support styleSheets[] array.
        if ( !document.styleSheets )
            return null;
        // Loop through the stylesheets in the html document.
        for ( var i = 0; i < document.styleSheets.length; i++ ) {
            var currentCssRules = getCssRules(document.styleSheets[i], htmlNode)
            if ( currentCssRules != null )
                cssRules.push.apply(cssRules, currentCssRules);
        }
        return cssRules;
    }
    /**
     * Checks if the CSSStyleRule has the property with 'important' attribute.
     * @param CSSStyleRule node
     * @param String property
     */
    function isImportant(node, property) {
        if ( node.style.getPropertyPriority && node.style.getPropertyPriority(property) == 'important' )
            return true;
        else if ( node.style.cssText && getPropertyPriority(node.style.cssText, property) == 'important' ) {
            // IE6-8
            // IE thinks that cssText is part of rule.style
            return true;
        }
    }
    /**
     * getPropertyPriority function for IE6-8
     * @param String cssText
     * @param String property
     */
    function getPropertyPriority(cssText, property) {
        var props = cssText.split(";");
        for ( var i = 0; i < props.length; i++ ) {
            if ( props[i].toLowerCase().indexOf(property.toLowerCase()) != -1 ) {
                // Found the correct property
                if ( props[i].toLowerCase().indexOf("!important") != -1 || props[i].toLowerCase().indexOf("! important") != -1) {
                    // IE automaticaly adds a space between ! and important...
                    return 'important'; // We found the important property for the property, return 'important'.
                }
            }
        }
        return ''; // We did not found the css property with important attribute.
    }
    /**
     * Outputs a debug message if debugging is enabled.
     * @param String msg
     */
    function debugMsg(msg) {
        if ( debug ) {
            // For debugging purposes.
            if ( window.console )
                console.log(msg);
            else
                alert(msg);
        }
    }
    /**
     * The main functionality required, to check whether a certain property of 
     * some html element has the important attribute.
     * 
     * @param HTMLElement htmlNode
     * @param String property
     */
    function hasImportant(htmlNode, property) {
        // First check inline style for important.
        if ( isImportant(htmlNode, property) ) {
            // For debugging purposes.
            debugMsg("Inline contains important!");
            return true;
        }
        var rules = getMatchedCSSRules(htmlNode);
        if ( rules == null ) {
            debugMsg("This browser does not support styleSheets...");
            return false;
        }
        /**
         * Iterate through the rules backwards, since rules are
         * ordered by priority where the highest priority is last.
         */
        for ( var i = rules.length; i-- > 0; ) {
            var rule = rules[i];
            if ( isImportant(rule, property) ) {
                // For debugging purposes.
                debugMsg("Css contains important!");
                return true;
            }
        }
        return false;
    }
    $(document).ready(function() {
        hasImportant($('#testdiv')[0], 'top');
    });
    

请参阅如何使用 .css() 应用 !important?

那里有一个函数可以添加到jQuery中。然后你像这样使用它:

console.log($('#testdiv').style().getPropertyPriority('top'));

您可以

尝试直接从CSS样式表中读取它。

看看这个问题的第二个答案:在 jQuery 中获取 CSS 规则的百分比值