你如何阅读JavaScript的CSS规则值?
我想返回一个CSS规则的所有内容的string,就像你看到的内联风格的格式。 我想能够做到这一点,而不知道什么是包含在一个特定的规则,所以我不能只是拉出他们的样式名称(如.style.width
等)
CSS:
.test { width:80px; height:50px; background-color:#808080; }
到目前为止的代码:
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')
从这里改编,基于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');
由于从“nsdel”接受的答案只有在文档中的一个样式表是可用的,所以这是适应性完整的工作解决scheme:
/** * 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; } } } }
注意:select器必须和CSS中的一样。
一些浏览器的差异要注意的是:
鉴于CSS:
div#a { ... } div#b, div#c { ... }
并以InsDel为例,课程将在FF中有两个类,在IE7中有三个类 。
我的例子说明这一点:
<!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>
解决scheme1(交叉浏览器)
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") ) ;
解决scheme2(交叉浏览器)
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'));
function getStyle(className) { document.styleSheets.item("menu").cssRules.item(className).cssText; } getStyle('.test')
注意:“menu”是你应用了CSS的元素ID。 “className”是我们需要获取文本的css类名。
我做了一个类似的帮助函数,显示了这个页面不需要的样式。 将<div>
附加到列出未使用的所有样式的正文。
(与萤火虫控制台一起使用)
(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 })()
为了得到更完整的结果,已经调整了julmot的答案。 此方法也将返回类是select器的一部分的样式。
//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; } }
此外,我已经做了一个函数,收集CSS样式定义到您提供的根节点的子树(通过jQueryselect器)。
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; }
请注意,如果一个类用相同的select器定义了几次,上面的函数将只会select第一个。 请注意,这个例子使用jQuery(但是cab比较容易被重写,不使用它)
我发现没有任何的build议,真正的工作。 这是一个更强大的查找类时的间距标准化。
//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)); }; })();
Chrome控制台正在运行。
//在IE中工作,不知道其他浏览器…
alert(classes[x].style.cssText);
这个版本将通过页面上的所有样式表。 对于我的需要,样式通常是在20多个样式表中的第二个到最后一个,所以我检查它们。
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; };
我添加了返回的对象的属性被parsing出样式/值:
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; };
以下是遍历页面中所有规则的代码:
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' : '')+' }'); });
基于@dude的答案,这应该返回一个对象的相关样式,例如:
.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%; }
这将返回:
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%"
码:
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' ) } } } }
我创build了一个search所有样式表的版本,并将匹配返回为键/值对象。 您还可以指定startsWith以匹配子样式。
getStylesBySelector('.pure-form-html', true);
收益:
{ ".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;" }
从:
.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; }
代码:
/** * 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; }
我在生产中使用它作为纯forms项目的一部分。 希望它有帮助。