我认为我们很多使用 Sass 映射的情况都可以用 CSS 自定义属性替换——但请听我解释一下。
在设计组件时,我们经常需要使用相同组件结构,但需要根据主题更改其背景或文字颜色 主题。 例如,在一个警报中,我们可能需要一个警告样式,一个错误样式和一个成功样式——每个样式可能略有不同,如下所示

我们可以用几种方法来解决这个问题,如果你在几年前问我,我会尝试用 Sass 映射来解决这个问题。 首先,我会从基本警报样式开始,但我会创建一个映射来保存所有数据
$alertStyles: (
error: (
theme: #fff5f5,
icon: 'error.svg',
darkTheme: #f78b8b
),
success: (
theme: #f0f9ef,
icon: 'success.svg',
darkTheme: #7ebb7a
),
warning: (
theme: #fff9f0,
icon: 'warning.svg',
darkTheme: #ffc848
)
);
然后我们可以遍历这些数据来更改我们的核心警报样式,如下所示
@each $state, $property in $alertStyles {
$theme: map-get($property, theme);
$darkTheme: map-get($property, darkTheme);
$icon: map-get($property, icon);
.alert-#{$state} {
background-color: $theme;
border-color: $darkTheme;
&:before {
background-color: $darkTheme;
background-image: url($icon);
}
.alert-title {
color: $darkTheme;
}
}
}
很复杂,对吧? 这会输出诸如 .alert-error
、.alert-success
和 .alert-warning
之类的类,每个类都包含一些 CSS,它们会覆盖默认的警报样式。
这将给我们留下一个类似于这个演示的内容
查看示例
警报 - Sass 循环 by Robin Rendle (@robinrendle)
在 CodePen 上。
但是! 我一直发现,使用 Sass 映射并遍历所有这些数据可能会变得笨拙且难以阅读。 在最近的项目中,我偶然发现了一些非常复杂的映射使用情况,然后慢慢地关闭了文件,就好像我闯入了犯罪现场一样。
如何保持代码简洁易懂? 好吧,我认为 CSS 自定义属性使得这类循环更容易阅读,因此在将来更容易编辑和重构。
让我们以上面的示例为例,对其进行重构,以便使用 CSS 自定义属性代替。 首先,我们将为 .alert
组件设置核心样式,如下所示
查看示例
警报 - 自定义变量 1 by Robin Rendle (@robinrendle)
在 CodePen 上。
在创建这些基本样式时,我们可以在 .alert
类中设置变量,如下所示
.alert {
--theme: #ccc;
--darkTheme: #777;
--icon: '';
background: var(--theme);
border: 1px solid var(--darkTheme);
/* other styles go here */
&:before {
background-image: var(--icon);
}
}
我们可以用 CSS 自定义属性做更多事情,不仅仅是将界面更改为深色模式或主题。 在尝试之前,我不知道可以像那样在自定义属性中设置图像——我只是认为它用于十六进制值。
无论如何! 从那里,我们可以通过在 .alert
中覆盖这些属性来为每个自定义 .alert
类(如 .alert-warning
)设置样式
.alert-success {
--theme: #f0f9ef;
--darkTheme: #7ebb7a;
--icon: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/14179/success.svg);
}
.alert-error {
--theme: #fff5f5;
--darkTheme: #f78b8b;
--icon: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/14179/error.svg);
}
.alert-warning {
--theme: #fff9f0;
--darkTheme: #ffc848;
--icon: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/14179/warning.svg);
}
就是这样! 我们将获得与 Sass 循环相同的视觉界面
查看示例
警报 - 自定义变量 2 by Robin Rendle (@robinrendle)
在 CodePen 上。
但是! 我认为这里在可读性方面有了巨大的改进。 这样看代码更容易理解。 使用 Sass 循环,我们似乎试图在一个地方做很多巧妙的事情——也就是说,将类嵌套在其他类中,并创建类名本身。 更不用说我们必须在原始的 Sass 映射和我们的样式之间来回切换了。
使用 CSS 自定义属性,所有样式都包含在原始 .alert
中。
就是这样! 我认为这里没什么可说的,除了 CSS 自定义属性可以使代码在将来更易读和更易维护。 我认为这是我们都应该感到兴奋的事情。
虽然还有一件事:在使用自定义属性时,我们可能应该注意浏览器支持,尽管它在 大多数情况下都支持。
您应该用固定 flex basis 替换之前的宽度
替换
width: 80px
用
flex: 0 0 60px;
这样可以使警报的这一部分更加一致。
太可惜了,自定义属性在 IE 中不起作用。
因此,大多数 Web 开发人员无法实际使用它们,直到 IE 消失,大约在宇宙热寂的时候。
这个例子不好。 当变量更有用时强迫使用 SASS 循环不是一个好的论点。 我希望看到一些从 SASS 循环中构建网格的东西,或者类似的东西,其中循环实际上意味着“循环”。
这很棒,而且更容易阅读。
不幸的是,我们必须相当多地支持 IE11(NHS 广泛使用它),因此我通常在 scss 中做类似的事情(即避免循环并更明确地将其拼写出来以提高可读性)。 我发现如果以后要搜索所有文件以查找此类样式名称,它也很有帮助。
同意。 您将获得文章中 CSS 示例的所有好处,并且与 IE11 兼容。
我敢肯定循环示例不会在生产中使用。 我宁愿看到一个混合,将颜色作为参数,这样您就可以分别输出每个类的内容,可读性更高。
为什么不在“错误框类型”类中直接覆盖属性? 这样可以提供更好的浏览器支持,更少的代码,并且可能更容易阅读? 这样将变量传递回原始类有什么优势?