我使用css变量进行了修改,找到了一个有趣的应用程序:你可以定义一个--color
变量,并根据类使用它作为不同属性的值:一个按钮可以填充其背景使用--color
,而标签控件可以使用带有--color
的边框底部来突出显示当前标签,如下所示:
:root {
font: 14px sans-serif;
--red: #f44;
--blue: #78f;
--green: #3c1;
--color: var(--blue);
}
.blue {
--color: var(--blue);
}
.red {
--color: var(--red);
}
.green {
--color: var(--green);
}
.fillbutton {
background: var(--color);
color: #fff;
padding: 0.25em 1em;
}
.borderbutton {
background: #fff;
border: 1px solid var(--color);
color: var(--color);
padding: 0.25em 1em;
}
.tab {
border-bottom: 1px solid #ccc;
padding: 0 1em;
line-height: 150%;
}
.tab.current {
border-bottom: 2px solid var(--color);
color: var(--color);
font-weight: bold;
}

<p>
<span class="fillbutton">Default</span>
<span class="fillbutton green">Green</span>
<span class="fillbutton red">Red</span>
<span class="borderbutton">Default</span>
<span class="borderbutton green">Green</span>
<span class="borderbutton red">Red</span>
</p>
<p><span class="tab">Tab1</span><span class="tab current">Tab2</span><span class="tab">Tab3</span></p>
<p><span class="tab red">Tab1</span><span class="tab red current">Tab2</span><span class="tab red">Tab3</span></p>
&#13;
通过定义改变--color的类,我们可以轻松地创建不同的颜色方案,而不必特定于我们想要样式的项目:只需要一个.red
类,而不是单独的{{1} } / .red.fillbutton
/ .red.borderbutton
由于某些浏览器不支持css变量,我认为我会尝试使用像scss这样的预处理器来复制此功能,但是scss变量似乎只是全局变量,因此不能模仿这个用例。有没有办法可以让我用scss以类似的DRY方式实现上述行为?
答案 0 :(得分:1)
由于通过SCSS生成CSS文件很简单,因此您可以使用单独的颜色变量SCSS文件和主“导入”SCSS文件(对于您可能拥有的所有其他SCSS文件)。你做的是你为每个颜色变量文件编译单独的CSS文件(例如,你可以有3个网站颜色主题,所以3个不同的颜色变量SCSS文件,然后3个不同的输出文件)。当用户选择不同的主题时,您只需记住用户选择的主题(cookie),并通过JS加载正确的CSS文件,而不是硬编码要使用的CSS文件。
它不是完全干的,因为你必须定义“主”输出SCSS文件(这些文件应该包括导入适当的颜色变量SCSS文件,该文件对每个文件进行更改,并导入“主导入”SCSS文件,对于每个颜色变量,它们总是相同的(所以如果你有3个颜色主题,则必须定义3个文件) - 尽管它也可以以编程方式完成。但是,通过这种方式,您可以启用网站的多个颜色主题,而无需担心当前缺乏对纯CSS变量的跨浏览器支持。只要您有预定义的颜色主题列表,这可能就是您的选择。
如果您没有预定义的颜色主题列表,并希望允许用户使用颜色选择器设置自己的颜色主题(并且不希望他们首先提交这些值,然后使用这些值,服务器另外,要从中生成CSS文件并将该文件提取给用户,您可以使用'currentColor'CSS属性。它受支持并且可以用作颜色变量,尽管它在功能方面远远超过新的CSS变量。基本上,通过currentColor可以访问父元素的color属性。所以你可以为父母提供类和样式(例如.blue有蓝色)然后通过currentColour设置几乎所有的样式。然后,当用户通过colourpicker或其他东西将蓝色变为绿色时,您可以通过JS将.blue的颜色更改为所选颜色。显然,您必须记住用户的选择,并在文档就绪时执行JS函数处理。这种解决方法肯定有它的缺点(例如,通过父级定义颜色将意味着许多额外的类/父元素,否则样式不需要),所以它也不是一个非常快速的方法,但它不依赖于生成多个CSS文件。
在我看来,如果你有预定义的颜色主题,最好使用SCSS变量并生成多个CSS文件。如果您允许用户完全修改其颜色主题,我会将这些值提交给服务器并生成正确的CSS文件,然后将该CSS文件提取给用户。但是,遵循此原则,在对CSS进行更改并部署这些更改时,不会更新CSS文件。所以这种方法也有其缺点。
在所有相关浏览器中都支持原生CSS变量之前,我担心没有完美的解决方案。
答案 1 :(得分:0)
在scss中尝试不同的策略后,我发现使用mixins的以下解决方案。首先,我们必须将所有颜色及其所需的类名定义为列表变量:
// define all colors
$colors: (red, #f44),
(green, #3c1),
(blue, #78f);
// define default color to be blue
$color: nth(nth($colors, 3), 2);
然后我们定义一个mixin colorize
,它首先使用默认的$color
定义给定的属性,然后迭代$colors
列表,使用父类对每个颜色类执行相同的操作选择器:
@mixin colorize($properties...) {
// for each property assign the default $color
@each $property in $properties {
#{$property}: $color;
}
// for each color class - assign the class color to each property
@each $cls, $col in $colors {
&.#{$cls} {
@each $property in $properties {
#{$property}: $col;
}
}
}
}
现在我们可以使用colorize
- mixin为一个或多个css属性指定特定于类的颜色:
.fillbutton {
@include colorize(background);
color: #fff;
padding: 0.25em 1em;
}
.borderbutton {
@include colorize(border-color, color);
background: #fff;
border: 1px solid;
padding: 0.25em 1em;
}
最后,在我们的html中使用它:
<span class="fillbutton green">Green</span>
<span class="fillbutton blue">Blue</span>
<span class="borderbutton">Default</span>
<span class="borderbutton green">Green</span>