gpt4 book ai didi

javascript - 具有通用属性的 CSSRules 组选择器

转载 作者:技术小花猫 更新时间:2023-10-29 12:43:55 25 4
gpt4 key购买 nike

此脚本包含在包含任何已声明样式(不包括由 style="" 设置的样式)的 HTML 文档中时,会将优化的样式表输出到页面。该脚本使用以下方法...

  1. 忽略任何 @: 规则以保留响应式样式。
  2. 将规则分成单个选择器规则,以便我们稍后测试继承。
  3. 删除适用于文档中不存在的选择器的规则,感谢 @RickHitchcock为此。
  4. 以相同的格式(不包括百分比)检索声明的和计算的样式,然后将两个值相互比较,然后删除该属性并再次检查。
  5. 如果声明的值与计算值匹配,并且通过删除属性值发生变化,则设置保留标志。这告诉我们该属性是否对元素有影响,如果没有元素受到该属性的影响...将其删除。
  6. 如果剩余的 CSSRule 中没有属性,则删除该规则。
  7. 作为副作用,大多数不更改浏览器默认设置的选择器将被删除(除非使用 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>';

future 的观众:这在 github 上可用 optiCSS (读:赏心悦目)

最佳答案

这看起来不错,我只有一个小建议。

按如下方式更改您的代码:

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规则是随你的代码一起输出的,但是经过上面的修改后它没有输出。

下一个挑战是简化那些fontborderpadding ……样式。


根据您的 Edit #25,您得到的字符串如下所示:

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 中没有包含双引号、分号、逗号或花​​括号的字符串内容。这会使事情变得有些复杂。

Fiddle

关于javascript - 具有通用属性的 CSSRules 组选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30519899/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com