¿Cómo se leen los valores de las reglas CSS con JavaScript?

Me gustaría devolver una cadena con todos los contenidos de una regla CSS, como el formato que verías en un estilo en línea. Me gustaría poder hacer esto sin saber qué contiene una regla en particular, así que no puedo simplemente sacarlos por nombre de estilo (como .style.width etc.)

El CSS:

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

El código hasta el momento:

 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') 

Adaptado de aquí , basándose en la respuesta de scunliffe:

 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) { (classes[x].cssText) ? alert(classes[x].cssText) : alert(classes[x].style.cssText); } } } getStyle('.test'); 

Como la respuesta aceptada de “nsdel” solo está disponible con una hoja de estilo en un documento, esta es la solución de trabajo completa adaptada:

  /** * 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; } } } } 

Aviso: el selector debe ser el mismo que en el CSS.

SOLUCIÓN 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") ) ; 

SOLUCIÓN 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')); 

Algunas diferencias de navegador a tener en cuenta:

Dado el CSS:

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

y dado el ejemplo de InsDel, las clases tendrán 2 clases en FF y 3 clases en IE7 .

Mi ejemplo ilustra esto:

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

Nota: “menú” es una ID de elemento que ha aplicado CSS. “className” es un nombre de clase css del que necesitamos obtener su texto.

No he encontrado ninguna de las sugerencias para realmente trabajar. Aquí hay uno más robusto que normaliza el espaciado al encontrar clases.

 //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)); }; })(); 

Aquí está en acción desde la consola de Chrome.

enter image description here

Hice una función auxiliar similar que muestra los estilos innecesarios para esta página. agrega un

al cuerpo que enumera todos los estilos que no se usaron.

(para ser utilizado con la consola Firebug)

 (function getStyles(){var CSSrules,allRules,CSSSheets, unNeeded, currentRule; CSSSheets=document.styleSheets; for(j=0;j"; } } } docBody=document.getElementsByTagName("body")[0]; allRulesContainer=document.createElement("div"); docBody.appendChild(allRulesContainer); allRulesContainer.innerHTML=unNeeded+isHover; return false })() 

Han adaptado la respuesta de julmot para obtener un resultado más completo. Este método también devolverá los estilos en los que la clase es parte del selector.

 //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 

Además, he creado una función que recostack las definiciones de estilo css en el subárbol de un nodo raíz que usted proporciona (a través de un selector de 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; } 

Tenga en cuenta que si una clase se define varias veces con el mismo selector, la función anterior solo captará la primera. Tenga en cuenta que el ejemplo usa jQuery (pero cab reescribe con relativa facilidad para no usarlo)

Aquí hay un código para iterar a través de todas las reglas en una página:

 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 { console.log(selector+' { '+propertyName+': '+propertyValue+(propertyPriority==='important' ? ' !important' : '')+' }'); }); 

// funciona en IE, no estoy seguro acerca de otros navegadores …

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

Esta versión pasará por todas las hojas de estilo en una página. Para mis necesidades, los estilos generalmente estaban en la penúltima de las más de 20 hojas de estilo, así que las controlé al revés.

  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 

Agregué el retorno del objeto donde los atributos son analizados estilo / valores:

 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 2) classStyles[style[1]]=style[2]; } return classStyles; } } } return false; }; 

Creé una versión que busca todas las hojas de estilo y devuelve coincidencias como un objeto clave / valor. También puede especificar startsWith para que coincida con los estilos secundarios.

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

devoluciones:

 { ".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;" } 

de:

 .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; } 

El código:

 /** * 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; } 

Estoy usando esto en producción como parte del proyecto de forma pura . Espero eso ayude.

Según @dude answer, esto debería devolver los estilos relevantes en un objeto, por ejemplo:

 .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%; } 

Esto volverá:

 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%" 

Código:

 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' ) } } } }