为什么我们更喜欢CSS(-变量)而不是SASS($变量)?

自几个月前CodyHouse Framework发布以来,尽管我们在这种环境中使用SASS,但许多用户问我们为什么选择CSS变量而不是SASS变量。 在本文中,我将讨论使用自定义属性的好处以及为什么它们在我们的工作流程中变得至关重要。



变量定义


在本文中,我假设您熟悉自定义CSS和SASS属性(或任何其他CSS预处理程序)的基础。 如果没有,让我们从一个基本示例开始:

在SCSS中:

$color-primary: hsl(220, 90%, 56%); .link { color: $color-primary; } 

在CSS中:

 :root { --color-primary: hsl(220, 90%, 56%); } .link { color: var(--color-primary); } 

自定义属性允许您定义变量而无需CSS扩展(即无需使用SASS)。

他们是一样的吗? 其实不! 与SASS变量不同,用户属性1)限于声明它们的元素,2)级联,3)可以在JavaScript中进行控制。 这三个功能为整个世界带来了新的可能性。 让我给你看一些实际的例子!

创建并应用颜色主题


这是一个示例,说明如何使用SASS变量创建两个(简化的)颜色主题:

 $color-primary: blue; $color-text: black; $color-bg: white; /*  */ $color-primary-invert: red; $color-text-invert: white; $color-bg-invert: black; .component { color: $color-text; background-color: $color-bg; a { color: $color-primary; } } .component--dark { color: $color-text-invert; background-color: $color-bg-invert; a { color: $color-primary-invert; } } 

在上面的示例中,我们有一个“默认”主题和一个“深色”主题,我们在其中反转背景和文本的颜色。 请注意,在一个黑暗的主题中,我们需要遍历使用颜色变量的每个属性,并使用新变量对其进行更新。

只要我们坚持简化(不现实)的示例,就不会出现问题。 但是,如果我们的组件包含很多元素怎么办? 我们将不得不重写所有使用颜色变量的属性,并用新的替换变量。 并且,如果您更改主要组件,则应仔细检查所有修饰符。 是的...不太方便!

创建框架时,我们基于CSS变量提出了另一种方法。 首先,让我们为颜色定义变量:

 :root, [data-theme="default"] { --color-primary: blue; /*   */ --color-bg: white; --color-contrast-lower: hsl(0, 0%, 95%); --color-contrast-low: hsl(240, 1%, 83%); --color-contrast-medium: hsl(240, 1%, 48%); --color-contrast-high: hsl(240, 4%, 20%); --color-contrast-higher: black; } [data-theme] { background-color: var(--color-bg); color: var(--color-contrast-high); } [data-theme="dark"] { --color-primary: red; /*   */ --color-bg: black; --color-contrast-lower: hsl(240, 6%, 15%); --color-contrast-low: hsl(252, 4%, 25%); --color-contrast-medium: hsl(240, 1%, 57%); --color-contrast-high: hsl(0, 0%, 89%); --color-contrast-higher: white; } 

注意:在上面的示例中,我们使用data- *属性应用颜色主题,但这与CSS变量和SASS变量无关。 此外,我们根据“对比水平”使用术语来定义中性值的比例

重要的一点是,我们不需要为第二,第三,第四...(深色)主题创建新的颜色变量。 与SASS不同,我们可以覆盖现有自定义属性的值。

这是将颜色变量应用于组件的方法:

 .component { color: var(--color-contrast-higher); background-color: var(--color-bg); border-bottom: 1px solid var(--color-contrast-low); a { color: var(--color-primary); } } 

深色版本的组件呢? 我们不需要其他CSS。 由于我们重新定义且不替换变量,因此仅在首次创建组件时才需要为颜色应用正确的变量。 在_colors.scss文件中设置颜色主题并将颜色变量应用于组件的元素之后,组件变得多么复杂并不重要。

您可以通过非常简单的方式应用颜色主题:

 <section data-theme="dark"> <div class="component"> <div class="child" data-theme="default"></div> </div> </section> 

在上面的示例中,我们将深色主题应用于该部分,并将默认主题应用于.child元素。 没错, 您可以投资色彩主题!

这可以通过使用CSS属性来实现。 这样就可以在最短的时间内完成如此有趣的事情。



如果您想了解有关使用CodyHouse框架管理颜色的更多信息,请参见以下链接:


字体比例管理


模块化比例尺是适用于印刷元素的一组和谐(尺寸)值。 这是使用SASS变量在SCSS中设置字体大小的方法:

 $text-xs: 0.694em; $text-sm: 0.833em; $text-base-size: 1em; $text-md: 1.2em; $text-lg: 1.44em; $text-xl: 1.728em; 

一种标准方法是使用第三方工具创建字体比例(或执行数学运算),然后将值导入您的样式,如上例所示。

创建框架时,我们决定将整个比例公式包含在_typography.scss文件中 这是我们使用CSS变量设置字体大小的方法:

 :root { //    --text-base-size: 1em; //   --text-scale-ratio: 1.2; --text-xs: calc((1em / var(--text-scale-ratio)) / var(--text-scale-ratio)); --text-sm: calc(var(--text-xs) * var(--text-scale-ratio)); --text-md: calc(var(--text-sm) * var(--text-scale-ratio) * var(--text-scale-ratio)); --text-lg: calc(var(--text-md) * var(--text-scale-ratio)); --text-xl: calc(var(--text-lg) * var(--text-scale-ratio)); --text-xxl: calc(var(--text-xl) * var(--text-scale-ratio)); --text-xxxl: calc(var(--text-xxl) * var(--text-scale-ratio)); } 

这种方法的优势是什么? 这样就可以通过仅编辑两个变量来控制整个打印系统:-- text-base-size (基本字体的大小)和--text-scale-ratio (比例因子)。

“您不能使用sass变量来做同样的事情吗?” 如果要在媒体查询的特定位置更改排版,则不可以:

 :root { @include breakpoint(md) { --text-base-size: 1.25em; --text-scale-ratio: 1.25; } } 

这是我们灵活方法的基石。 因为我们使用相对的Ems单位,所以当您更改--text-base-size (基本字体的大小)时,这会影响版式和间距。 结果,您将获得一个无需调整组件级别的媒体查询就可以调整所有组件大小的系统。



以下是一些有用的相关链接:


距离刻度控制


间隔比例尺等同于类型比例尺,但适用于空间值。 再次,在结构中包含比例尺公式使我们能够控制间隔系统并使之响应:

 :root { --space-unit: 1em; --space-xxxxs: calc(0.125 * var(--space-unit)); --space-xxxs: calc(0.25 * var(--space-unit)); --space-xxs: calc(0.375 * var(--space-unit)); --space-xs: calc(0.5 * var(--space-unit)); --space-sm: calc(0.75 * var(--space-unit)); --space-md: calc(1.25 * var(--space-unit)); --space-lg: calc(2 * var(--space-unit)); --space-xl: calc(3.25 * var(--space-unit)); --space-xxl: calc(5.25 * var(--space-unit)); --space-xxxl: calc(8.5 * var(--space-unit)); --space-xxxxl: calc(13.75 * var(--space-unit)); } @supports(--css: variables) { :root { @include breakpoint(md) { --space-unit: 1.25em; } } } 

与上面讨论的版式方法结合使用时,此方法特别强大。 仅需几行CSS,您就会获得响应组件:



我喜欢在此间距系统中使用Ems模块的另一件事是,如果间距和印刷尺寸恰好在媒体查询中的特定点,则几乎可以肯定它们在媒体查询的所有点都正确。您更新值--space-unit。 因此,我可以设计而不必调整浏览器窗口的大小(除非我想更改组件的行为)。

更多相关链接:


在组件级别编辑“垂直节奏”


与SASS变量不同,我们可以覆盖CSS变量的值。 使用此属性的一种方法是将自定义属性添加到其他自定义属性,从而创建可在组件级别进行编辑的“控件”。

这是一个示例,当您设置文本组件的垂直间距时,您可能希望为元素指定行高边距底

 .article { h1, h2, h3, h4 { line-height: 1.2; margin-bottom: $space-xs; } ul, ol, p, blockquote { line-height: 1.5; margin-bottom: $space-md; } } 

但是,此速度取决于文本的使用位置。 例如,如果您希望文本更简洁,则需要创建一个组件变体(修饰符),在其中应用不同的间隔值:

 .article--sm { h1, h2, h3, h4 { line-height: 1.1; margin-bottom: $space-xxxs; } ul, ol, p, blockquote { line-height: 1.4; margin-bottom: $space-sm; } } 

...每次,如果您想更新“垂直节奏”。

这是一种基于CSS变量的替代方法:

 .text-component { --component-body-line-height: calc(var(--body-line-height) * var(--line-height-multiplier, 1)); --component-heading-line-height: calc(var(--heading-line-height) * var(--line-height-multiplier, 1)); --line-height-multiplier: 1; --text-vspace-multiplier: 1; h1, h2, h3, h4 { line-height: var(--component-heading-line-height); margin-bottom: calc(var(--space-xxxs) * var(--text-vspace-multiplier)); } h2, h3, h4 { margin-top: calc(var(--space-sm) * var(--text-vspace-multiplier)); } p, blockquote, ul li, ol li { line-height: var(--component-body-line-height); } ul, ol, p, blockquote, .text-component__block, .text-component__img { margin-bottom: calc(var(--space-sm) * var(--text-vspace-multiplier)); } } 

--line-height-multiplier--text-vspace-multiplier是两个文本组件控制变量。 当我们创建.text-component类的修饰符时,为了编辑垂直间隔,我们只需要重新定义以下两个变量:

 .article.text-component { //     --line-height-multiplier: 1.13; //     --text-vspace-multiplier: 1.2; //    } 

如果您想自己尝试并注意以下事项:



抽象行为成分


覆盖组件值的能力可以以不同的方式使用。 通常,在任何时候您可以在一个或多个变量中抽象出组件的行为时,当需要编辑该组件(或需要创建组件变体)时,您的工作就会变得更加轻松。

一个示例是我们的Auto Sized Grid组件,其中我们使用CSS网格来创建布局,画廊元素根据CSS中指定的最小宽度自动填充可用空间,然后抽象元素的最小宽度并将其存储在变量中。


最小宽度值是创建“自动调整尺寸”网格组件选项时唯一需要更改的内容。

有什么收获?


简而言之:浏览器支持...您可以使用PostCss插件以本文所述的所有方式使用CSS变量。 较旧的浏览器(<IE11)有很多限制。 否则,可以免费使用。 请查阅我们的文档 ,以获取有关今天使用CSS变量的局限性的更多信息。

我可以在预处理器中使用CSS变量吗?


是的 尽管SASS(或任何其他预处理器)允许您执行CSS中无法完成的工作,并且需要它,但为什么不使用它呢? SASS不是用户访问您的网站时必须下载的库。 这是您工作流程中的工具。 例如,我们使用SASS定义与CSS变量一起使用的颜色函数。

结论


在本文中,我们看了几个示例,这些示例演示了使用CSS变量而不是SASS变量的优势。 我们专注于它们如何允许您创建“控件”,以加快更改组件或设置影响印刷术和间隔的规则的过程。 我们已经考虑了很多,希望您可以从这篇文章中学到一些知识并将其用于您的工作中。

Source: https://habr.com/ru/post/zh-CN456302/


All Articles