您能否检测到 dom 节点的样式何时设置为“自动”

Can you detect when a dom node's style is set to 'auto'?

本文关键字:设置 何时 自动 样式 检测 节点 dom      更新时间:2023-09-26

使用示例 CSS:

.thing { height: auto }

和 HTML:

<div class="thing">The quick brown fox jumps over a lazy dog.</div>

是否可以检测到 .thing 的高度设置为"自动"?

以下方法返回值:

jQuery('.thing').height()        // n
jQuery('.thing').css('height')   // 'npx'
getComputedStyle(node).height    // 'npx'

有什么方法可以告诉我浏览器正在从"自动"计算这些值?

是的,有一种方法,但这不是一个有趣的方法。 你要做的是:

  1. 遍历所有styletags和链接的样式表。
  2. 然后获取所有样式标记中所有cssRulesselectorText

    styletag.sheet.cssRules.selectorText
    

    或适用于 IE <9

    styletag.styleSheet.cssRules.selectorText
    
  3. 获取所有父级元素idclasstagName,以找出标签获取属性的可能方法。

  4. 找到指向您的元素的所有可能组合cssRules列表
  5. 检查这些cssRules cssRules.style.width是否为自动。

或者以相反的方式做,并找到所有cssRules style.width == 'auto';无论哪种方式,如果没有大量代码,它都不容易获得

jQuery('.thing').each(function (i,n){
  console.log( $(n).style.height);// if not then just try to simply find the n.style.height
});
//this is another way // at least in ff it would work :)
window.document.styleSheets[0].cssRules[0].style.height

希望它有所帮助,否则你有很多挖掘要做:)

对于您看到的第二个选项[0]意味着您必须循环,因为可能有不同的文件名等......

完整示例:

var ss = window.document.styleSheets;
for(i=0;i<ss.length;i++){
    var rules = ss[i].cssRules;
    for(j=0;j<rules.length;j++){//loop style sheets
        var rule = rules[j];
        if(rule.selectorText=='thing'){//loop each stylesheet rule
             console.log(rule.style.height);
              // should return height for everytime height is used with every .thing in any of your stylesheets attached :)
        }
    }
}

请注意

您必须从跨域中转义那些,例如,如果您已包含 <link ....="...jquery.com.../ui.css" />它不起作用,因为这可能被视为安全风险(跨域)...

这不是最有效的解决方案,特别是对于旧的IE版本,但它应该工作得很好:

  1. 测量元素的高度
  2. 将一些内容附加到元素中,例如 <div style="clear: left; height: 30px">Test</div>
  3. 测试新高度,如果它已更改,您的元素具有高度自动
  4. 删除内容

这是我的实现:

$.fn.hasAutoHeight = function() {
    if (this.length === 0) return;
    var self = this.first();
    var height = self.css("height");
    var position = self.css("position");
    // Check for inline elements
    if (self.css("display") === "inline" && self.css("float") === "none") {
        var position = self.css("position");
        if (position === "static" || position === "relative") return true;  
    }
    // Quick check to see if a style height is set
    if ($.style(self[0], "height") !== "") return false;
    // Otherwise use the long route
    var test = $('<div style="clear: both; height: 30px">Test</div>');
    self.append(test);
    var hasAutoHeight = self.css("height") !== height;
    test.css("color", "red").remove();
    return hasAutoHeight;
};

笔记:

  • 如果 CSS 中有height: auto !important;规则,"快速检查"行可能无法正常工作,在这种情况下,您始终必须走很长的路线。
  • 这在 DOM 交互方面效率不高,因此您的应用程序希望尽可能缓存此结果。
  • 我不愿意在插件内部缓存结果,因为类/CSS 规则可能会更改并使结果无效。
  • 这不适用于没有主体的元素,例如<img><br>

以下是上述建议的更完整实现:

$("*").data("autoHeight", "false");
var stylesheets = window.document.styleSheets;
for (i=0; i < stylesheets.length; i++) {
    var rules = stylesheets[i].cssRules;
    for (j = 0; j < rules.length; j++) {
        var rule = rules[j];
        var style = rule.style.getPropertyValue("height");
        var auto = !style || style.match(/^'s*auto's*(!important)?$/);
        $(rule.selectorText).each(function() {
            var elem = $(this);
            if (asSpecific(rule.selectorText, $(elem).data("autoHeightSelector"))) {
                $(elem).data("autoHeight", !!auto);
                $(elem).data("autoHeightSelector", rule.selectorText);
            }
        });
    }
}

您需要实现asSpecific(a, b),如果 css 选择器a至少与选择器b一样具体,则应实现,例如 p#foo a#barp.foo更具体。您还需要考虑!important标志。

这可能很有用:http://www.w3.org/TR/CSS2/cascade.html#specificity

这应该为每个元素添加一个数据属性,指定它在 CSS 中是否具有自动高度样式,但您还需要检查样式属性并考虑默认样式。