1

我对 css 变量进行了修改,找到了一个有趣的应用程序:您可以定义一个--color变量,并将其用作基于类的不同属性的值:按钮的背景可以用 填充--color,而选项卡控件可以使用使用border-bottom--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>

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

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

4

2 回答 2

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 设置几乎所有内容的样式。然后,当用户通过颜色选择器或其他东西将蓝色更改为绿色时,您可以更改 . 通过 JS 将蓝色变为所选颜色。显然,您必须记住用户的选择并在准备好文档时执行处理该选择的 JS 函数。这种解决方法当然有它的缺点(例如,通过父母定义颜色将意味着大量额外的类/父元素,否则样式化不需要这些),所以它也不是一个完全快速的方法,但它不依赖于生成多个 CSS 文件。

在我看来,如果您有预定义的颜色主题,最好使用 SCSS 变量并生成多个 CSS 文件。如果您允许用户完全修改他们的颜色主题,我会将这些值提交给服务器并生成适当的 CSS 文件,然后将该 CSS 文件获取给用户。但是,遵循此原则,CSS 文件不会在您更改 CSS 并部署这些更改时更新。所以这种方法也有它的缺点。

在所有相关浏览器都正确支持原生 CSS 变量之前,我担心没有完美的解决方案。

于 2017-05-10T09:33:07.490 回答
-1

在 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,它首先使用 default 定义给定的属性$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>
于 2017-05-10T12:21:00.933 回答