此脚本包含在包含任何声明样式(不包括style=""
设置的样式)的HTML文档中时,将向页面输出优化的样式表。该脚本使用以下方法...
@
或:
规则,按原样保留自适应样式。CSSRule
中没有属性,则删除该规则。font
而不是font-*
和类似的选项将激活其余的设置那个属性)。在包含与动态元素相关的样式的网站上运行此脚本时,我只是将它们包装在媒体查询中
@media (min-width: 0px) {
/* This says that these styles always apply */
}
如何将具有共同属性的选择器分组?
(Demo)
var stylesheets = document.styleSheets, stylesheet, i;
var ruleText = "";
if(stylesheets && stylesheets.length) {
for (i = 0; (stylesheet = stylesheets[i]); i++) {
var rules = stylesheet.rules, rule, j;
if(rules && rules.length) {
for (j = 0; (rule = rules[j]); j++) {
if(rule.type === rule.STYLE_RULE) {
if(rule.selectorText.indexOf(',') >= 0) {
var newRules = [];
var selectors = rule.selectorText.split(','), selector, k;
for(k = 0; (selector = selectors[k]); k++) {
var styles = rule.style, style, l;
var elements = document.querySelectorAll(selector.trim()), element, l;
if(elements.length) {
var styleString = '';
for(m = 0; (style = styles[m]); m++) {
styleString += style + ': ' + styles.getPropertyValue(style) + "; ";
}
newRules.push((selector.trim() + ' { ' + styleString.trim() + ' }'));
}
}
stylesheet.deleteRule(j);
for(k = 0; (rule = newRules[k]); k++) {
stylesheet.insertRule(rule, j);
}
}
}
}
for (j = 0; (rule = rules[j]); j++) {
if(rule.type === rule.STYLE_RULE && rule.selectorText.indexOf(':') < 0) {
var styles = rule.style, style, k;
var elements = document.querySelectorAll(rule.selectorText);
if(elements && elements.length) {
for(k = 0; (style = styles[k]); k++) {
var value = styles.getPropertyValue(style);
if(value.indexOf('%') < 0) {
var elements = document.querySelectorAll(rule.selectorText), element, m;
var keep = false;
for(m = 0; (element = elements[m]); m++) {
var computed = window.getComputedStyle(element).getPropertyValue(style);
var match1 = value === computed;
styles.removeProperty(style);
var computed = window.getComputedStyle(element).getPropertyValue(style);
var match2 = value === computed;
styles.setProperty(style, value);
if( match1 && !match2 ) {
keep = true;
}
}
if(!keep) {
styles.removeProperty(style);
}
}
}
ruleText += rule.cssText + "\n";
}
} else {
ruleText += rule.cssText + "\n";
}
}
}
}
}
document.body.innerHTML = '<pre>' + ruleText + '<pre>';
未来观众:这在github上以optiCSS的形式提供(阅读:令人愉悦)
答案 0 :(得分:1)
这看起来很棒,我只有一个小建议。
按如下方式更改您的代码:
for (j = 0; rule = rules[j]; j++) {
var styles = rule.style, style, k;
var elements = document.querySelectorAll(rule.selectorText);
if(elements.length) {
for(k = 0; style = styles[k]; k++) {
...
}
console.log(rule.cssText);
}
}
这将阻止输出没有任何匹配HTML的规则。
在 this Fiddle 中,li
规则与您的代码一起输出,但不会通过上述修改输出。
下一个挑战是简化font
,border
,padding
,......样式。
html { margin-right: 0px; margin-left: 0px; height: 100%; }
body { margin-right: 0px; margin-left: 0px; height: 100%; margin-top: 0px; }
body { margin-bottom: 5px; background-color: rgb(255, 0, 0); }
@media (max-width: 500px) {
body { background: blue; }
}
以下是如何将其变为:
html {margin-right:0px;margin-left:0px;height:100%;}
body {margin-right:0px;margin-left:0px;height:100%;margin-top:0px;margin-bottom:5px;background-color:rgb(255 0 0);}
@media (max-width: 500px) {
body { background: blue; }
}
在此过程中,您将获得两个对象:
html {"margin-right":"0px;","margin-left":"0px;","height":"100%;"}
body {"margin-right":"0px;","margin-left":"0px;","height":"100%;","margin-top":"0px;","margin-bottom":"5px;","background-color":"rgb(255, 0, 0);"}
首先,将您的媒体查询输出分开,因为您不希望它受到影响:
var ruleText = "", mediaText = "";
...
if (styles.length) {
ruleText += rule.cssText + "\n";
}
} else {
mediaText += rule.cssText + "\n";
}
然后在循环之后放置它:
var inp= ruleText.split('\n'),
out= '',
selectors= {};
inp.forEach(function(val) {
if(val) {
var selector= val.split(/ *{/)[0],
styles= val.split(/{ */)[1].split('}')[0].split(/; */);
selectors[selector]= selectors[selector] || {};
styles.forEach(function(val) {
if(val) {
var st= val.split(/ *: */);
selectors[selector][st[0]]= st[1]+';';
}
});
}
});
for(var i in selectors) {
out+= i+' '+JSON.stringify(selectors[i]).replace(/[,"]/g,'')+'\n';
}
document.body.innerHTML= '<pre>'+out+mediaText+'</pre>';
为简单起见,上面的代码假设CSS中没有包含双引号,分号,逗号或花括号的字符串内容。这会使事情变得复杂。