如何在scss中伪造css变量?

时间:2017-05-10 09:11:13

标签: css sass css-variables

我使用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;
&#13;
&#13;

通过定义改变--color的类,我们可以轻松地创建不同的颜色方案,而不必特定于我们想要样式的项目:只需要一个.red类,而不是单独的{{1} } / .red.fillbutton / .red.borderbutton

由于某些浏览器不支持css变量,我认为我会尝试使用像scss这样的预处理器来复制此功能,但是scss变量似乎只是全局变量,因此不能模仿这个用例。有没有办法可以让我用scss以类似的DRY方式实现上述行为?

2 个答案:

答案 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>