小程序使用sass_如何使用Sass Maps生成所有实用程序类

小程序使用sass

by Sarah Dayan

通过莎拉·达扬

如何使用Sass Maps生成所有实用程序类 (How to generate all your utility classes with Sass Maps)

One of the powers of utility classes lies in giving you access to every small concept of your design system in a slew of contexts. If your main color is royal blue, you can apply it as a text color on anything with a .text-royal-blue class, as a background color with a .bg-royal-blue class, and so on.

实用程序类的强大功能之一在于,使您可以在一系列上下文中访问设计系统的每个小概念。 如果您的主要颜色是宝蓝色,则可以将其作为文本颜色应用于具有.text-royal-blue类的任何颜色,也可以作为具有.bg-royal-blue类的背景颜色,等等。

But how do you write them in an effective, consistent, and scalable way?

但是,您如何以有效,一致和可扩展的方式编写它们?

TL;DR: this post goes in-depth in the how-to stuff. If you want to understand the whole thought process, read on. Otherwise you can grab the code on GitHub or test it out on SassMeister.

TL; DR :这篇文章深入介绍了操作方法。 如果您想了解整个思考过程,请继续阅读。 否则,您可以在GitHub上获取代码或在SassMeister对其进行测试。

$royal-blue: #0007ff;
.text-royal-blue {  color: $royal-blue;}
.bg-royal-blue {  background: $royal-blue;}
...

That’s repetitive. Not only are you hand-typing the color name and value every single time, but you’re also creating an unmaintainable system. What happens when you have ten color utilities like these, and you need to add one more color to the scheme?

那是重复的。 您不仅要每次手动键入颜色名称和值,而且还要创建一个无法维护的系统。 当您有十个这样的颜色实用程序,并且需要向该方案中再添加一种颜色时,会发生什么情况?

You shouldn’t spend time on mindless, tedious tasks. That’s what scripting languages are for. If you’re already using Sass, you need to harness its power and let it help you.

您不应该花时间在漫不经心的乏味任务上。 这就是脚本语言的用途 。 如果您已经在使用Sass,则需要利用其强大功能并为您提供帮助。

什么是萨斯地图? (What are Sass Maps?)

Maps are a Sass data type that represent an association between keys and values. If you’re familiar with other scripting languages, you could see it as an associative array. It allows you to store data, and have a name to reference each piece.

映射是Sass数据类型,表示键和值之间的关联 。 如果您熟悉其他脚本语言,则可以将其视为关联数组 。 它允许您存储数据,并有一个名称来引用每个部分。

Lists and maps are a bit similar, in that they’re both storing a collection of data and they’re both iterable in an @each loop. But unlike lists, maps make it easy to reference any piece of information by calling it by its name. This makes it ideal for grouping logically related information.

列表和映射有点相似,它们都存储数据集合,并且都可以在@each循环中迭代。 但是,与列表不同,地图通过按名称来调用它可以轻松引用任何信息。 这使其非常适合对逻辑相关信息进行分组。

$colors: (  mako-grey: #404145,  fuel-yellow: #ecaf2d,  pastel-green: #5ad864);

让我们添加一些逻辑 (Let’s add some logic)

Now that our colors are neatly stored inside a map, we need to iterate it to generate our utility classes. To do that, we’ll use the @each directive inside a @mixin that we’ll include later in our utility base class.

现在我们的颜色已经整齐地存储在地图中,我们需要对其进行迭代以生成实用程序类。 为了做到这一点,我们将使用@each一个内部指令@mixin ,我们稍后将在我们的公用事业基础类包括。

@mixin color-modifiers {  // do stuff}

Let’s now use the @each directive to loop through $colors and fetch the right data.

现在让我们使用@each指令遍历$colors并获取正确的数据。

@mixin color-modifiers {  @each $name, $hex in $colors {    // do stuff  }}

We’re iterating $colors and at every loop, the current key will be referenced in $name and the color’s hexadecimal code will be in $hex. We can start building our ruleset.

我们迭代$colors ,在每个循环中,当前键将在$name引用,而颜色的十六进制代码将在$hex 。 我们可以开始构建规则集。

@mixin color-modifiers {  @each $name, $hex in $colors {    &-#{$name} {      color: $hex;    }  }}

Now for every pair in the map, @each will generate a ruleset that references the parent selector with the & character, appends a hyphen and the color’s name, and sets the color attribute to the current hexadecimal value.

现在,对于映射中的每个对, @each将生成一个规则集,该规则集使用&字符引用父选择器,并附加连字符和颜色名称,并将color属性设置为当前的十六进制值。

In other words, doing this:

换句话说,这样做:

.text {  @include color-modifiers;}

Will generate this:

将生成此:

.text-mako-grey {  color: #404145;}.text-fuel-yellow {  color: #ecaf2d;}.text-pastel-green {  color: #5ad864;}

Pretty neat, uh? Actually, we barely scratched the surface. For now, our mixin can only output rules with the color attribute. What if we want to create some utility classes for background colors?

很整洁吧? 实际上,我们几乎没有刮擦表面。 目前,我们的mixin只能输出带有color属性的规则。 如果我们想为背景色创建一些实用程序类怎么办?

Fortunately, Sass allows us to pass arguments to mixins.

幸运的是,Sass允许我们将参数传递给mixins。

@mixin color-modifiers($attribute: 'color') {  @each $name, $hex in $colors {    &-#{$name} {      #{$attribute}: $hex;    }  }}

Now we can specify exactly what attribute we want.

现在,我们可以确切指定所需的属性。

Let’s improve our mixin a little more: right now, the modifier prefix is a hardcoded hyphen. This means your classes will always be in the form of .base-modifier. What if you need it to change? What if you also want to generate some BEM-flavored modifiers (two hyphens)? Again, that’s something we can achieve by using arguments.

让我们进一步改善混合效果:现在,修饰符前缀是硬编码的连字符。 这意味着您的类将始终采用.base-modifier的形式。 如果您需要更改该怎么办? 如果您还想生成一些BEM修饰符(两个连字符)怎么办? 同样,这可以通过使用参数来实现。

@mixin color-modifiers($attribute: 'color', $prefix: '-') {  @each $name, $hex in $colors {    &#{$prefix}#{$name} {      #{$attribute}: $hex;    }  }}

Now we can generate modifier classes with any kind of prefix we want. So, doing this:

现在,我们可以生成带有所需前缀的修饰符类。 因此,这样做:

.text {  @include color-modifiers($prefix: '--');}

Will generate this:

将生成此:

.text--mako-grey {  color: #404145;}.text--fuel-yellow {  color: #ecaf2d;}.text--pastel-green {  color: #5ad864;}

Pro tip: in Sass, you can explicitly name arguments when you call a mixin or a function (like in the example above). This avoids having to provide them in order.

提示 :在Sass中,可以在调用mixin或函数时显式命名参数(如上例所示)。 这样避免了必须按顺序提供它们。

地图内的地图 (Maps within maps)

I like to use a slightly different color system so I can manage tonal variations. By nesting maps within maps, I have a clean and readable way to keep shades grouped together.

我喜欢使用略有不同的颜色系统,以便可以管理色调变化。 通过将地图嵌套在地图中,我可以采用一种清晰易读的方式将阴影分组在一起。

$colors: (  grey: (    base: #404145,    light: #c7c7cd  ),  yellow: (    base: #ecaf2d  ),  green: (    base: #5ad864  ));

If we want to work with such a color system, we need to adapt our mixin so it goes iterating a level deeper.

如果我们要使用这样的颜色系统,则需要调整我们的mixin,使其更深层次地迭代。

@mixin color-modifiers($attribute: 'color', $prefix: '-', $separator: '-') {  @each $name, $color in $colors {    &#{$prefix}#{$name} {      @each $tone, $hex in $color {        &#{$separator}#{$tone} {          #{$attribute}: $hex;        }      }    }  }}

We added a new argument, $separator, to link the color’s name and the tone. We could have used the $prefix but it doesn’t have the same purpose. Using a dedicated variable with a default value is a better choice, as it gives us full freedom when we use the mixin.

我们添加了一个新参数$separator ,以链接颜色的名称和色调。 我们本可以使用$prefix但它的目的不同。 使用具有默认值的专用变量是更好的选择,因为当我们使用mixin时,它为我们提供了充分的自由。

Now, doing this:

现在,这样做:

.text {  @include color-modifiers;}

Will generate this:

将生成此:

.text-grey-base {  color: #404145;}.text-grey-light {  color: #c7c7cd;}.text-yellow-base {  color: #ecaf2d;}.text-green-base {  color: #5ad864;}

Great! We now have helpers composed of a base class, a color, and a tone. One thing we need to improve, though, is how base color modifiers are outputted. We actually don’t need that -base suffix — the base class and color are enough.

大! 现在,我们有一些由基类,颜色和色调组成的助手。 但是,我们需要改进的一件事是如何输出基本颜色修改器。 我们实际上不需要-base后缀-基类和颜色就足够了。

What we must do is check for the tone in the nested @each loop, and only output it and the $separator when it’s not “base.” Luckily for us, Sass already has everything we need.

我们必须做的是检查嵌套@each循环中的音调,并仅在它不是“ base”时输出它和$separator 。 对我们来说幸运的是,Sass已经拥有了我们需要的一切。

@ if,@ else,if() (@if, @else, if())

Our first instinct might be to use the @if/@else directives. Problem is, this would force us to repeat code and will result in complicated code. Instead, we’re going to use one of Sass’ secret weapons: if().

我们的本能可能是使用@if/@else指令。 问题是,这将迫使我们重复代码并导致复杂的代码。 相反,我们将使用Sass的秘密武器之一: if()

if() is Sass’ conditional (ternary) operator. It takes three arguments: a condition and two return statements. If the condition is met, if() will return the first statement. Otherwise, it will return the second one. You can see it as an @if/@else shorthand.

if()是Sass的条件(三元)运算符。 它包含三个参数:一个条件和两个return语句。 如果满足条件, if()将返回第一条语句。 否则,它将返回第二个。 您可以将其视为@if/@else简写。

@mixin color-modifiers($attribute: 'color', $prefix: '-', $separator: '-', $base: 'base') {  @each $name, $color in $colors {    &#{$prefix}#{$name} {      @each $tone, $hex in $color {        &#{if($tone != $base, #{$separator}#{$tone}, '')} {          #{$attribute}: $hex;        }      }    }  }}

Every time the nested @each loop will parse a $tone that’s different from “base,” it will return the $separator and the $tone as the class suffix. Else, it will return nothing, leaving the class as is.

每次嵌套的@each循环将解析与“ base”不同的$tone ,它将返回$separator$tone作为类后缀。 否则,它将不返回任何内容,而按原样保留类。

.text-grey {  color: #404145;}.text-grey-light {  color: #c7c7cd;}.text-yellow {  color: #ecaf2d;}.text-green {  color: #5ad864;}

全部干燥 (DRY-ing it all up)

In a real-world project, chances are you’ll want to use various map structures. For example, you could have one-level deep maps for font sizes and two-levels deep maps for colors. You’re not going to write a different mixin for each depth level. That would be repetitive and unmaintainable. You need to be able to rely on a single mixin to handle that.

在现实世界的项目中,您可能会想使用各种地图结构。 例如,您可能具有用于字体大小的一级深层映射和用于颜色的两级深层映射。 您不会为每个深度级别编写不同的mixin 。 那将是重复的和不可维持的。 您需要能够依靠单个mixin来处理。

We want a generic mixin to generate all modifiers, and one that’s able to handle multidimensional maps. If you compare the two mixins we came up with in this tutorial, you’ll notice they look a lot alike. The only difference is that one performs an extra loop before printing the computed CSS declaration. This is a typical job for a recursive mixin.

我们希望一个通用的mixin生成所有修改器,并且能够处理多维地图。 如果将本教程中我们想到的两种混合器进行比较,您会发现它们看起来非常相似。 唯一的区别是,在打印计算出CSS声明之前,执行了一个额外的循环。 这是递归mixin的典型工作。

It will begin with an @each directive where we can start building our selector. This is where we’ll check if the current $key equals to “base” so we can decide to output it or not. Then, we’ll check if the current $value is a map itself: if yes, we need to run the mixin again from where we are and pass it the nested map. Otherwise, we can print the CSS declaration.

它将以@each指令开始,在这里我们可以开始构建选择器。 在这里,我们将检查当前的$key等于“ base”,以便我们决定是否输出它。 然后,我们将检查当前的$value本身是否是地图:如果是,我们需要从我们所在的位置再次运行mixin并将其传递给嵌套地图。 否则,我们可以打印CSS声明。

@mixin modifiers($map, $attribute, $prefix: '-', $separator: '-', $base: 'base') {  @each $key, $value in $map {    &#{if($key != $base, #{$prefix}#{$key}, '')} {      @if type-of($value) == 'map' {        @include modifiers($value, $attribute, $separator);      }      @else {        #{$attribute}: $value;      }    }  }}

And voilà! This mixin will work with maps of any depth. Feel free to use it in your own projects! If you like it, you can show some love by starring it on GitHub. Also, if you want to improve it, please leave a comment on the gist so I can update it ?

! 这个mixin可以与任何深度的地图一起使用。 随时在自己的项目中使用它! 如果喜欢,可以通过在GitHub上加注星标来表达爱意。 另外,如果您要改进它,请在要点上发表评论,以便我进行更新?

Originally published at frontstuff.io.

最初发布在frontstuff.io上

翻译自: https://www.freecodecamp.org/news/how-to-generate-all-your-utility-classes-with-sass-maps-8921ab3b4508/

小程序使用sass

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值