使用Javascript/jQuery从外部样式表获取CSS值

65

如果所涉及的元素是动态生成的,且该元素还未被生成,是否可以从页面的外部CSS获取其值?

我看到的jQuery方法是$('element').css('property');,但这需要在页面上存在element。有没有一种方法可以找出属性在CSS中设置的值,而不是元素的计算样式?

我是否必须添加一个隐藏的元素副本到我的页面,以便我可以访问其样式属性?

5个回答

65

使用jQuery:

// Scoping function just to avoid creating a global
(function() {
    var $p = $("<p></p>").hide().appendTo("body");
    console.log($p.css("color"));
    $p.remove();
})();
p {color: blue}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

直接使用DOM:

// Scoping function just to avoid creating a global
(function() {
    var p = document.createElement('p');
    document.body.appendChild(p);
    console.log(getComputedStyle(p).color);
    document.body.removeChild(p);
})();
p {color: blue}

注意: 在这两种情况下,如果您正在加载外部样式表,您需要等待它们加载以便在元素上看到它们的效果。无论是 jQuery 的 ready 还是 DOM 的 DOMContentLoaded 事件都不会做到这一点,您需要通过观察它们是否加载完成来确保。


1
是的,那正是它的含义。 - karim79
4
思路:“如果样式是嵌套的,请确保它被嵌套在正确的元素下面。” 例如,CSS:.container .content {} 和 jQuery:var $p = $("<div class=" content "></div>").hide().appendTo("container"); - David Hobs
17
我们能否在将元素添加到DOM之前获取其CSS属性值呢?比如 $('<div class="content" />').css('color') 这对我有效。 - Pierre de LESPINAY
3
似乎这在 Firefox 中可以工作,但在 Webkit 浏览器中不行(已尝试过 Chromium 和 Android 2.x 浏览器)。 - pfalcon
你能否用同样的方法处理 height 吗?因为它似乎并没有起作用... - Karol
谢谢你拥有良好的 jQuery 风格(在第一个示例中使用 var $p 而不是 var p)。我完全不知道这个约定,看到你的答案让我搜索了一下,想知道为什么你这么做!对于任何阅读此评论并不熟悉该约定的人,此问题的前两个答案很好地解释了这是怎么回事 :) - svenevs

19

通常情况下,你应该让浏览器应用所有规则,然后询问浏览器结果。但是在你确实需要从样式表中获取值的罕见情况下,你可以使用这个: (JSFiddle)

function getStyleSheetPropertyValue(selectorText, propertyName) {
    // search backwards because the last match is more likely the right one
    for (var s= document.styleSheets.length - 1; s >= 0; s--) {
        var cssRules = document.styleSheets[s].cssRules ||
                document.styleSheets[s].rules || []; // IE support
        for (var c=0; c < cssRules.length; c++) {
            if (cssRules[c].selectorText === selectorText) 
                return cssRules[c].style[propertyName];
        }
    }
    return null;
}

alert(getStyleSheetPropertyValue("p", "color"));

需要注意的是,这种方法非常脆弱,因为您必须提供完整的选择器文本以匹配您要查找的规则(它不会被解析),并且它不处理重复条目或任何类型的优先级规则。很难想象在什么情况下使用这种方法是一个好主意,但这里只是作为一个例子。


2
遗憾的是,CSS 是一种可怕的语言,具有“特异性优先级”原则,这意味着该函数只能在大约一半的情况下起作用。 此外 - selectorText 可以不同,但仍然指向相同的元素。 - oriadam

7

针对Karim79的问题,我想分享一下我的函数版本答案。我已经多次使用过这个方法,以下是我的代码:

function getClassStyles(parentElem, selector, style){
    elemstr = '<div '+ selector +'></div>';
    var $elem = $(elemstr).hide().appendTo(parentElem);
        val = $elem.css(style);
    $elem.remove();
    return val;
}
val = getClassStyles('.container:first', 'class="title"', 'margin-top');
console.warn(val);

这个例子假定您有一个 class="container" 的元素,并且您正在查找该元素中 title 类的 margin-top 样式。当然,根据您的需要进行更改。
在样式表中:
 .container .title{ margin-top:num; }

请告诉我你的想法——你会对此进行修改吗?如果会,你会怎么修改呢?谢谢!


很棒的代码片段,我稍微改了一下,因为使用 div 阻止了我在样式表中查找像这样构建的规则(table.TreeGrid td.tab)。 - Ally
1
我建议将选择器作为第一个属性(并且解析#和.也可以),将“style”属性作为函数的第二个属性,将parentElem作为最后一个属性;然后您可以将parentElem设置为非必需项(并使用全局样式)。接下来,请记住,父元素可能不存在。但对我来说,这是一个非常好的起点,所以+1 :-) - tomis

2

我编写了一个帮助函数,它接受一个包含要从给定CSS类中检索的CSS属性的对象,并填充实际的CSS属性值。示例已包含。

function getStyleSheetValues(colScheme) {
    var tags='';
    var obj= colScheme;
    
    // enumerate css classes from object
    for (var prop in obj) { 
        if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
            tags+= '<span class="'+prop+'"></span>';
        } 
    } 
    
    // generate an object that uses the given classes
    tags= $('<div>'+tags+'</div>').hide().appendTo("body");
    
    // read the class properties from the generated object
    var idx= 0;
    for (var prop in obj) { 
        if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
            var nobj= obj[prop];
            for (var nprop in nobj) { 
                if (nobj.hasOwnProperty(nprop) && typeof(nobj[nprop])=="string") { 
                    nobj[nprop]= tags.find("span:eq("+idx+")").css(nobj[nprop]);
                }
            }
            idx++;
        } 
    } 
    tags.remove();
}

// build an object with css class names where each class name contains one 
// or more properties with an arbitrary name and the css attribute name as its value.
// This value will be replaced by the actual css value for the respective class.
var colorScheme= { chart_wall: {wallColor:'background-color',wallGrid:'color'}, chart_line1: { color:'color'} };

$(document).ready(function() {
    getStyleSheetValues(colorScheme);

    // debug: write the property values to the console;     
    if (window.console) {
        var obj= colorScheme;
        for (var prop in obj) { 
            if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
                var nobj= obj[prop];
                for (var nprop in nobj) { 
                    if (nobj.hasOwnProperty(nprop)) { 
                        console.log(prop+'.'+nprop +':'+ nobj[nprop]);
                    }
                }
            } 
        } 
        // example of how to read an individual css attribute value
        console.log('css value for chart_wall.wallGrid: '+colorScheme.chart_wall.wallGrid);
    }
});

0
我写了这个JS函数,似乎也适用于嵌套类:
用法:
var style = get_css_property('.container-class .sub-container-class .child-class', 'margin');
console.log('style');


function get_css_property(class_name, property_name){
    class_names = class_name.split(/\s+/);
    var container = false;
    var child_element = false;

    for (var i = class_names.length - 1; i >= 0; i--) {
        if(class_names[i].startsWith('.'))
            class_names[i] = class_names[i].substring(1);
        var new_element = $.parseHTML('<div class="' + class_names[i] + '"></div>');
        if(!child_element)
            child_element = new_element;
        if(container)
            $(new_element).append(container);
        container = new_element;
    }
    $(container).hide().appendTo('body');
    var style = $(child_element).css(property_name);
    $(container).remove();
    return style;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接