Làm cách nào để bạn đọc các giá trị quy tắc CSS với JavaScript?


115

Tôi muốn trả về một chuỗi có tất cả nội dung của quy tắc CSS, giống như định dạng bạn thấy trong kiểu nội tuyến. Tôi muốn có thể làm điều này mà không cần biết những gì được chứa trong một quy tắc cụ thể, vì vậy tôi không thể chỉ kéo chúng ra bằng tên kiểu (như .style.widthv.v.)

CSS:

.test {
    width:80px;
    height:50px;
    background-color:#808080;
}

Mã cho đến nay:

function getStyle(className) {
    var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules
    for(var x=0;x<classes.length;x++) {
        if(classes[x].selectorText==className) {
            //this is where I can collect the style information, but how?
        }
    }
}
getStyle('.test')

xin vui lòng kiểm tra điều này cũng. stackoverflow.com/questions/53592919/…
Mithilesh Kumar

Câu trả lời:


90

Được điều chỉnh từ đây , dựa trên câu trả lời của scunliffe:

function getStyle(className) {
    var cssText = "";
    var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
    for (var x = 0; x < classes.length; x++) {        
        if (classes[x].selectorText == className) {
            cssText += classes[x].cssText || classes[x].style.cssText;
        }         
    }
    return cssText;
}

alert(getStyle('.test'));

11
Lưu ý rằng className phải khớp chính xác với bộ chọn được sử dụng trong tệp CSS. Ví dụ getStyle (". Article a") sẽ không tìm thấy gì nếu một kiểu được mô tả như thế này ".article a, article a: hover {color: #ccc;}".
Vilius Paulauskas

1
Điều này không hoạt động trong chrome, nhưng nó hoạt động trong firefox, vấn đề có thể là gì ??
Johnydep

13
nếu có nhiều bảng định kiểu, thì bạn cũng sẽ cần lặp qua các bảng đó.for (var i = 0; i <document.styleSheets.length; i ++) {var s = document.styleSheets [i];}
surya

@surya Xem câu trả lời của tôi cho một giải pháp làm việc đầy đủ được điều chỉnh
anh bạn

2
@Johnydep var classesphải document.styleSheets[0].rules[0].cssRulesở trong Chrome. Điều này có thể được thêm (một cách sáng tạo) vào dấu chấm trong câu trả lời.
Henrik Christensen

23

Vì câu trả lời được chấp nhận từ "nsdel" chỉ có sẵn với một biểu định kiểu trong tài liệu, đây là giải pháp hoạt động đầy đủ được điều chỉnh:

    /**
     * Gets styles by a classname
     * 
     * @notice The className must be 1:1 the same as in the CSS
     * @param string className_
     */
    function getStyle(className_) {

        var styleSheets = window.document.styleSheets;
        var styleSheetsLength = styleSheets.length;
        for(var i = 0; i < styleSheetsLength; i++){
            var classes = styleSheets[i].rules || styleSheets[i].cssRules;
            if (!classes)
                continue;
            var classesLength = classes.length;
            for (var x = 0; x < classesLength; x++) {
                if (classes[x].selectorText == className_) {
                    var ret;
                    if(classes[x].cssText){
                        ret = classes[x].cssText;
                    } else {
                        ret = classes[x].style.cssText;
                    }
                    if(ret.indexOf(classes[x].selectorText) == -1){
                        ret = classes[x].selectorText + "{" + ret + "}";
                    }
                    return ret;
                }
            }
        }

    }

Lưu ý: Bộ chọn phải giống như trong CSS.


global_nó chỉ là một bí danh cho đối tượng cửa sổ. Tôi đã chỉnh sửa đoạn mã. Nó sẽ hoạt động ngay bây giờ
chàng

3
mã của bạn không thành công nếu một biểu định kiểu không có quy tắc hoặc cssRules (có thể xảy ra!) thêm if (! lớp) tiếp tục; sau var class = styleSheets [i] .rules || styleSheets [i] .cssRules; var classLength = class.length; xem bản chỉnh sửa của tôi
kofifus

1
hoạt động, nhưng phải trả lại một đối tượng thay vì một chuỗi
brauliobo

@kofifus cách tiếp cận của bạn đã được thêm vào
anh chàng

Lưu ý rằng điều này không hoạt động kể từ GC versio 64.0: stackoverflow.com/questions/48753691/…
Shalev Levi

18

GIẢI PHÁP 1 (CROSS-BROWSER)

function GetProperty(classOrId,property)
{ 
    var FirstChar = classOrId.charAt(0);  var Remaining= classOrId.substring(1);
    var elem = (FirstChar =='#') ?  document.getElementById(Remaining) : document.getElementsByClassName(Remaining)[0];
    return window.getComputedStyle(elem,null).getPropertyValue(property);
}

alert( GetProperty(".my_site_title","position") ) ;

GIẢI PHÁP 2 (CROSS-BROWSER)

function GetStyle(CLASSname) 
{
    var styleSheets = document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    for(var i = 0; i < styleSheetsLength; i++){
        if (styleSheets[i].rules ) { var classes = styleSheets[i].rules; }
        else { 
            try {  if(!styleSheets[i].cssRules) {continue;} } 
            //Note that SecurityError exception is specific to Firefox.
            catch(e) { if(e.name == 'SecurityError') { console.log("SecurityError. Cant readd: "+ styleSheets[i].href);  continue; }}
            var classes = styleSheets[i].cssRules ;
        }
        for (var x = 0; x < classes.length; x++) {
            if (classes[x].selectorText == CLASSname) {
                var ret = (classes[x].cssText) ? classes[x].cssText : classes[x].style.cssText ;
                if(ret.indexOf(classes[x].selectorText) == -1){ret = classes[x].selectorText + "{" + ret + "}";}
                return ret;
            }
        }
    }
}

alert( GetStyle('.my_site_title') );

6

Một số khác biệt về trình duyệt cần lưu ý:

Cung cấp CSS:

div#a { ... }
div#b, div#c { ... }

và cho ví dụ của InsDel, các lớp sẽ có 2 lớp trong FF và 3 lớp trong IE7 .

Ví dụ của tôi minh họa điều này:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <style>
    div#a { }
    div#b, div#c { }
    </style>
    <script>
    function PrintRules() {
    var rules = document.styleSheets[0].rules || document.styleSheets[0].cssRules
        for(var x=0;x<rules.length;x++) {
            document.getElementById("rules").innerHTML += rules[x].selectorText + "<br />";
        }
    }
    </script>
</head>
<body>
    <input onclick="PrintRules()" type="button" value="Print Rules" /><br />
    RULES:
    <div id="rules"></div>
</body>
</html>

4

Đây là mã để lặp qua tất cả các quy tắc trong một trang:

function iterateCSS(f) {
  for (const styleSheet of window.document.styleSheets) {
    const classes = styleSheet.rules || styleSheet.cssRules;
    if (!classes) continue;

    for (const cssRule of classes) {
      if (cssRule.type !== 1 || !cssRule.style) continue;
      const selector = cssRule.selectorText, style=cssRule.style;
      if (!selector || !style.cssText) continue;
      for (let i=0; i<style.length; i++) {
        const propertyName=style.item(i);
        if (f(selector, propertyName, style.getPropertyValue(propertyName), style.getPropertyPriority(propertyName), cssRule)===false) return;
      }
    }
  }
}

iterateCSS( (selector, propertyName, propertyValue, propertyPriority, cssRule) => {
  console.log(selector+' { '+propertyName+': '+propertyValue+(propertyPriority==='important' ? ' !important' : '')+' }');
});


2
function getStyle(className) {
    document.styleSheets.item("menu").cssRules.item(className).cssText;
}
getStyle('.test')

Lưu ý: "menu" là ID phần tử mà bạn đã áp dụng CSS. "className" một tên lớp css mà chúng ta cần lấy văn bản của nó.


Bạn có chắc điều này đang hoạt động? (AFAIK itemphương thức nhận một chỉ mục số nguyên, không phải một className).
Julien Kronegg

hoàn toàn vô nghĩa
tnt-rox

2

Tôi không tìm thấy đề xuất nào thực sự hiệu quả. Đây là một cách mạnh mẽ hơn giúp chuẩn hóa khoảng cách khi tìm lớp.

//Inside closure so that the inner functions don't need regeneration on every call.
const getCssClasses = (function () {
    function normalize(str) {
        if (!str)  return '';
        str = String(str).replace(/\s*([>~+])\s*/g, ' $1 ');  //Normalize symbol spacing.
        return str.replace(/(\s+)/g, ' ').trim();           //Normalize whitespace
    }
    function split(str, on) {               //Split, Trim, and remove empty elements
        return str.split(on).map(x => x.trim()).filter(x => x);
    }
    function containsAny(selText, ors) {
        return selText ? ors.some(x => selText.indexOf(x) >= 0) : false;
    }
    return function (selector) {
        const logicalORs = split(normalize(selector), ',');
        const sheets = Array.from(window.document.styleSheets);
        const ruleArrays = sheets.map((x) => Array.from(x.rules || x.cssRules || []));
        const allRules = ruleArrays.reduce((all, x) => all.concat(x), []);
        return allRules.filter((x) => containsAny(normalize(x.selectorText), logicalORs));
    };
})();

Đây là hoạt động từ bảng điều khiển Chrome.

nhập mô tả hình ảnh ở đây


1
Đây là cơ chế của tất cả các câu trả lời trên trang này. Tôi thậm chí còn đi xa hơn khi nói rằng điều này nên được đăng trên github
Jacksonkr

Điều này không hoạt động trong IE11, vì Array.map () với cú pháp được cung cấp không được hỗ trợ. Tôi khuyên bạn nên thay đổi nó thành hàm cũ () {return xxx; } cú pháp để tương thích tốt hơn. Nếu không, câu trả lời tuyệt vời!
Demonblack

1
Tôi đã sửa đổi điều này để hoạt động với IE11 (ví dụ: ES5). Dưới đây là một JSFiddle với tất cả mọi thứ bạn cần: jsfiddle.net/xp5r8961
Demonblack

1

Tôi đã tạo một chức năng trợ giúp tương tự để hiển thị các kiểu không cần thiết cho trang này. nối một<div> vào phần thân liệt kê tất cả các kiểu không được sử dụng.

(được sử dụng với bảng điều khiển firebug)

(function getStyles(){var CSSrules,allRules,CSSSheets, unNeeded, currentRule;
CSSSheets=document.styleSheets;

for(j=0;j<CSSSheets.length;j++){
for(i=0;i<CSSSheets[j].cssRules.length;i++){
    currentRule = CSSSheets[j].cssRules[i].selectorText;

    if(!document.querySelectorAll(currentRule).length){ 
       unNeeded+=CSSSheets[j].cssRules[i].cssText+"<br>"; 
  }       
 }
}

docBody=document.getElementsByTagName("body")[0];
allRulesContainer=document.createElement("div");
docBody.appendChild(allRulesContainer);
allRulesContainer.innerHTML=unNeeded+isHover;
return false
})()

1

Đã điều chỉnh câu trả lời của julmot để có được kết quả đầy đủ hơn. Phương thức này cũng sẽ trả về các kiểu mà lớp là một phần của bộ chọn.

//Get all styles where the provided class is involved
//Input parameters should be css selector such as .myClass or #m
//returned as an array of tuples {selectorText:"", styleDefinition:""}
function getStyleWithCSSSelector(cssSelector) {
    var styleSheets = window.document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    var arStylesWithCSSSelector = [];

    //in order to not find class which has the current name as prefix
    var arValidCharsAfterCssSelector = [" ", ".", ",", "#",">","+",":","["];

    //loop through all the stylessheets in the bor
    for(var i = 0; i < styleSheetsLength; i++){
        var classes = styleSheets[i].rules || styleSheets[i].cssRules;
        var classesLength = classes.length;
        for (var x = 0; x < classesLength; x++) {
            //check for any reference to the class in the selector string
            if(typeof classes[x].selectorText != "undefined"){
                var matchClass = false;

                if(classes[x].selectorText === cssSelector){//exact match
                    matchClass=true;
                }else {//check for it as part of the selector string
                    //TODO: Optimize with regexp
                    for (var j=0;j<arValidCharsAfterCssSelector.length; j++){
                        var cssSelectorWithNextChar = cssSelector+ arValidCharsAfterCssSelector[j];

                        if(classes[x].selectorText.indexOf(cssSelectorWithNextChar)!=-1){
                            matchClass=true;
                            //break out of for-loop
                            break;
                        }
                    }
                }

                if(matchClass === true){
                    //console.log("Found "+ cssSelectorWithNextChar + " in css class definition " + classes[x].selectorText);
                    var styleDefinition;
                    if(classes[x].cssText){
                        styleDefinition = classes[x].cssText;
                    } else {
                        styleDefinition = classes[x].style.cssText;
                    }
                    if(styleDefinition.indexOf(classes[x].selectorText) == -1){
                        styleDefinition = classes[x].selectorText + "{" + styleDefinition + "}";
                    }
                    arStylesWithCSSSelector.push({"selectorText":classes[x].selectorText, "styleDefinition":styleDefinition});
                }
            }
        }
    }
    if(arStylesWithCSSSelector.length==0) {
        return null;
    }else {
        return arStylesWithCSSSelector;    
    }
}

Ngoài ra, tôi đã tạo một hàm thu thập các định nghĩa kiểu css vào cây con của nút gốc mà bạn cung cấp (thông qua bộ chọn jquery).

function getAllCSSClassDefinitionsForSubtree(selectorOfRootElement){
    //stack in which elements are pushed and poped from
    var arStackElements = [];
    //dictionary for checking already added css class definitions
    var existingClassDefinitions = {}

    //use jquery for selecting root element
    var rootElement = $(selectorOfRootElement)[0];
    //string with the complete CSS output
    var cssString = "";

    console.log("Fetching all classes used in sub tree of " +selectorOfRootElement);
    arStackElements.push(rootElement);
    var currentElement;

    while(currentElement = arStackElements.pop()){
        currentElement = $(currentElement);
        console.log("Processing element " + currentElement.attr("id"));

        //Look at class attribute of element 
        var classesString = currentElement.attr("class");
        if(typeof classesString != 'undefined'){
            var arClasses = classesString.split(" ");

            //for each class in the current element
            for(var i=0; i< arClasses.length; i++){

                //fetch the CSS Styles for a single class. Need to append the . char to indicate its a class
                var arStylesWithCSSSelector = getStyleWithCSSSelector("."+arClasses[i]);
                console.log("Processing class "+ arClasses[i]);

                if(arStylesWithCSSSelector != null){
                    //console.log("Found "+ arStylesWithCSSSelector.length + " CSS style definitions for class " +arClasses[i]);
                    //append all found styles to the cssString
                    for(var j=0; j< arStylesWithCSSSelector.length; j++){
                        var tupleStyleWithCSSSelector = arStylesWithCSSSelector[j];

                        //check if it has already been added
                        if(typeof existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] === "undefined"){
                            //console.log("Adding " + tupleStyleWithCSSSelector.styleDefinition);
                            cssString+= tupleStyleWithCSSSelector.styleDefinition;
                            existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] = true;
                        }else {
                            //console.log("Already added " + tupleStyleWithCSSSelector.styleDefinition);
                        }
                    }
                }
            }
        }
        //push all child elments to stack
        if(currentElement.children().length>0){
            arStackElements= arStackElements.concat(currentElement.children().toArray());
        }
    }

    console.log("Found " + Object.keys(existingClassDefinitions).length + " CSS class definitions");
    return cssString;
}

Lưu ý rằng nếu một lớp được định nghĩa nhiều lần với cùng một bộ chọn, thì hàm trên sẽ chỉ chọn lớp đầu tiên. Lưu ý rằng ví dụ sử dụng jQuery (nhưng cab tương đối dễ dàng được viết lại để không sử dụng nó)


1
sẽ là tuyệt vời để có một giải pháp jquery không (và một jsfiddle ..)
kofifus

0

// hoạt động trên IE, không chắc chắn về các trình duyệt khác ...

alert(classes[x].style.cssText);

0

Phiên bản này sẽ đi qua tất cả các bảng định kiểu trên một trang. Đối với nhu cầu của tôi, các kiểu thường ở thứ 2 đến cuối cùng trong số hơn 20 bảng định kiểu, vì vậy tôi kiểm tra ngược lại.

    var getStyle = function(className){
        var x, sheets,classes;
        for( sheets=document.styleSheets.length-1; sheets>=0; sheets-- ){
            classes = document.styleSheets[sheets].rules || document.styleSheets[sheets].cssRules;
            for(x=0;x<classes.length;x++) {
                if(classes[x].selectorText===className) {
                    return  (classes[x].cssText ? classes[x].cssText : classes[x].style.cssText);
                }
            }
        }
        return false;
    };

0

Tôi đã thêm trả về của đối tượng trong đó các thuộc tính được phân tích cú pháp ra kiểu / giá trị:

var getClassStyle = function(className){
    var x, sheets,classes;
    for( sheets=document.styleSheets.length-1; sheets>=0; sheets-- ){
        classes = document.styleSheets[sheets].rules || document.styleSheets[sheets].cssRules;
        for(x=0;x<classes.length;x++) {
            if(classes[x].selectorText===className){
                classStyleTxt = (classes[x].cssText ? classes[x].cssText : classes[x].style.cssText).match(/\{\s*([^{}]+)\s*\}/)[1];
                var classStyles = {};
                var styleSets = classStyleTxt.match(/([^;:]+:\s*[^;:]+\s*)/g);
                for(y=0;y<styleSets.length;y++){
                    var style = styleSets[y].match(/\s*([^:;]+):\s*([^;:]+)/);
                    if(style.length > 2)
                        classStyles[style[1]]=style[2];
                }
                return classStyles;
            }
        }
    }
    return false;
};

style.cssText.match(...).1là null hay không phải là một đối tượng
dude

Uncaught ReferenceError: classStyleTxt is not defined
Jacksonkr

0

Tôi đã tạo một phiên bản tìm kiếm tất cả các bảng định kiểu và trả về các kết quả phù hợp dưới dạng đối tượng khóa / giá trị. Bạn cũng có thể chỉ định startWith để phù hợp với các kiểu con.

getStylesBySelector('.pure-form-html', true);

trả lại:

{
    ".pure-form-html body": "padding: 0; margin: 0; font-size: 14px; font-family: tahoma;",
    ".pure-form-html h1": "margin: 0; font-size: 18px; font-family: tahoma;"
}

từ:

.pure-form-html body {
    padding: 0;
    margin: 0;
    font-size: 14px;
    font-family: tahoma;
}

.pure-form-html h1 {
    margin: 0;
    font-size: 18px;
    font-family: tahoma;
}

Mật mã:

/**
 * Get all CSS style blocks matching a CSS selector from stylesheets
 * @param {string} className - class name to match
 * @param {boolean} startingWith - if true matches all items starting with selector, default = false (exact match only)
 * @example getStylesBySelector('pure-form .pure-form-html ')
 * @returns {object} key/value object containing matching styles otherwise null
 */
function getStylesBySelector(className, startingWith) {

    if (!className || className === '') throw new Error('Please provide a css class name');

    var styleSheets = window.document.styleSheets;
    var result = {};

    // go through all stylesheets in the DOM
    for (var i = 0, l = styleSheets.length; i < l; i++) {

        var classes = styleSheets[i].rules || styleSheets[i].cssRules || [];

        // go through all classes in each document
        for (var x = 0, ll = classes.length; x < ll; x++) {

            var selector = classes[x].selectorText || '';
            var content = classes[x].cssText || classes[x].style.cssText || '';

            // if the selector matches
            if ((startingWith && selector.indexOf(className) === 0) || selector === className) {

                // create an object entry with selector as key and value as content
                result[selector] = content.split(/(?:{|})/)[1].trim();
            }
        }
    }

    // only return object if we have values, otherwise null
    return Object.keys(result).length > 0 ? result : null;
}

Tôi đang sử dụng điều này trong sản xuất như một phần của dự án dạng thuần túy . Hy vọng nó giúp.


0

Tôi phải đối mặt với cùng một vấn đề. Và với sự giúp đỡ của những người bạn, tôi đã nghĩ ra một giải pháp thực sự thông minh để giải quyết triệt để vấn đề đó (chạy trên chrome).

Trích xuất tất cả hình ảnh từ mạng

 function AllImagesUrl (domain){
  return  performance.getEntries()
    .filter( e=> 
       e.initiatorType == "img" &&
       new RegExp(domain).test(e.name) 
    )
  .map( e=> e.name.replace('some cleaning work here','') ) ```

0
const getStyle = query => [...document.querySelector(query).computedStyleMap().entries()].map(e=>(e[1]+=[],e)).map(e=>e.join`:`+';').join`\n`

Trong một dòng, in ra css đã tạo cho bất kỳ truy vấn nào.


-2

Dựa trên câu trả lời @dude, điều này sẽ trả về các kiểu có liên quan trong một đối tượng, ví dụ:

.recurly-input {                                                                                                                                                                             
  display: block;                                                                                                                                                                            
  border-radius: 2px;                                                                                                                                                                        
  -webkit-border-radius: 2px;                                                                                                                                                                
  outline: 0;                                                                                                                                                                                
  box-shadow: none;                                                                                                                                                                          
  border: 1px solid #beb7b3;                                                                                                                                                                 
  padding: 0.6em;                                                                                                                                                                            
  background-color: #f7f7f7;                                                                                                                                                                 
  width:100%;                                                                                                                                                                                
}

Điều này sẽ trả về:

backgroundColor:
"rgb(247, 247, 247)"
border
:
"1px solid rgb(190, 183, 179)"
borderBottom
:
"1px solid rgb(190, 183, 179)"
borderBottomColor
:
"rgb(190, 183, 179)"
borderBottomLeftRadius
:
"2px"
borderBottomRightRadius
:
"2px"
borderBottomStyle
:
"solid"
borderBottomWidth
:
"1px"
borderColor
:
"rgb(190, 183, 179)"
borderLeft
:
"1px solid rgb(190, 183, 179)"
borderLeftColor
:
"rgb(190, 183, 179)"
borderLeftStyle
:
"solid"
borderLeftWidth
:
"1px"
borderRadius
:
"2px"
borderRight
:
"1px solid rgb(190, 183, 179)"
borderRightColor
:
"rgb(190, 183, 179)"
borderRightStyle
:
"solid"
borderRightWidth
:
"1px"
borderStyle
:
"solid"
borderTop
:
"1px solid rgb(190, 183, 179)"
borderTopColor
:
"rgb(190, 183, 179)"
borderTopLeftRadius
:
"2px"
borderTopRightRadius
:
"2px"
borderTopStyle
:
"solid"
borderTopWidth
:
"1px"
borderWidth
:
"1px"
boxShadow
:
"none"
display
:
"block"
outline
:
"0px"
outlineWidth
:
"0px"
padding
:
"0.6em"
paddingBottom
:
"0.6em"
paddingLeft
:
"0.6em"
paddingRight
:
"0.6em"
paddingTop
:
"0.6em"
width
:
"100%"

Mã:

function getStyle(className_) {

    var styleSheets = window.document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    for(var i = 0; i < styleSheetsLength; i++){
        var classes = styleSheets[i].rules || styleSheets[i].cssRules;
        if (!classes)
            continue;
        var classesLength = classes.length;
        for (var x = 0; x < classesLength; x++) {
            if (classes[x].selectorText == className_) {
                return _.pickBy(classes[x].style, (v, k) => isNaN(parseInt(k)) && typeof(v) == 'string' && v && v != 'initial' && k != 'cssText' )
            }
        }
    }

}

bất cứ thứ gì mà không có lodash được sử dụng? _.pickBy không tồn tại nếu không.
mpag

k & v được đảo ngược dựa trên những gì bạn đang yêu cầu .... sẽ được trả lại_.pickBy(classes[x].style, (k,v) => isNaN(parseInt(k)) && typeof(v) == 'string' && v && v != 'initial' && k != 'cssText' )
mpag
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.