如何在 SASS 中使用嵌套元素构造 BEM 修改器
Posted
技术标签:
【中文标题】如何在 SASS 中使用嵌套元素构造 BEM 修改器【英文标题】:How to structure BEM modifiers with nested elements in SASS 【发布时间】:2017-11-11 00:49:42 【问题描述】:SASS + BEM 在大多数情况下几乎是天作之合,但我的一个常见难题是了解如何在使用 SASS 父选择器时在影响其子元素的元素上最好地定义 BEM 修饰符。
我在 SASS 中使用 BEM 样式语法定义了以下组件:
.card
background-color: #FFF;
&__value
font-size: 2em;
color: #000;
由于 SASS 的父选择器,这很有效。它使相关代码井井有条且自成体系。
但是当我需要添加一个使用父选择器改变子元素的修饰符时,这个想法很快就崩溃了:
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
&__value // Is this going to work?
font-size: 3em;
不。它会生成这个:
.card
padding: 2em;
.card__value
font-size: 1.5em;
color: #000;
.card--big
padding: 2.5em;
.card--big__value // Wrong
font-size: 3em;
以某种方式获得这个选择器会更有意义:
.card--big .card__value
font-size: 3em;
这样做的原因是,您可以简单地将修饰符添加到***元素并使其影响任何或所有子元素。
我尝试了几种方法:
使用两个结构
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
.card--big
padding: 2.5em;
&__value
font-size: 3em;
这很有效(尤其是在这个简化的演示中),但是在具有许多修饰符的更复杂的组件集合中,这可能是维护和保持无错误的潜在痛苦。此外,如果可能的话,最好继续使用 SASS 父选择器。
为元素使用变量
.card
$component: &; // Set the variable here
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
#$component__value // Use it here
font-size: 3em;
这很好用。但是将元素定义为变量似乎有点愚蠢。也许这是做到这一点的唯一真正方法......我不确定。有没有更好的选择来构建它?
【问题讨论】:
好点!这是最干净的嵌套方式,而不是使用一百个 mixin。我认为您的问题是自我回答的。 可以用一个字符&--big
变成 &--big &
- 查看我的答案了解详情。希望对将来遇到此问题的人有用
【参考方案1】:
为什么不这样做呢?
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
&--big &__value
font-size: 3em;
【讨论】:
是的,这是可能的解决方案之一。不理想,因为您重复组件类名称,但还不错。 真的!我也喜欢你的变量选项,非常有创意!【参考方案2】:您可以将修饰符拆分为不同的结构,但嵌套在 .card
选择器中,如下所示:
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
&--big &__value
padding: 2.5em;
这又会产生这个:
.card
padding: 2em;
.card__value
font-size: 1.5em;
color: #000;
.card--big
padding: 2.5em;
.card--big .card__value
padding: 2.5em;
我认为这是一个几乎完美的方式,虽然它不是完美的嵌套 我希望这是一个帮助!
【讨论】:
【参考方案3】:我刚刚找到了一个更好的方法来使用 sass 实现这一点,通过使用变量来存储父选择器的值,您可以在任何级别的嵌套中使用它!
例如,这里我将.card
选择器存储在$this 变量中,并像#$this
一样重用它
所以这段代码
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
$this: &;
&--big
padding: 2.5em;
#$this__value
font-size: 3em;
将编译为
.card
padding: 2em;
.card__value
font-size: 1.5em;
color: #000;
.card--big
padding: 2.5em;
.card--big .card__value
font-size: 3em;
这个答案的灵感来自css-tricks 上的这篇文章。感谢Sergey Kovalenko
【讨论】:
谢谢,但这正是我在问题中提出的建议。 我看你是对的,我在你刚才问的时候看到了你的问题,现在我看到了这篇文章,所以我才发布它【参考方案4】:您可以在这里使用另一种模式。
这将: - 将实际的卡片修饰符与其元素的修饰符分开 - 将修改后的样式保留在相同元素的选择器中,因此您无需上下滚动代码即可查看正在修改的内容 - 将阻止更具体的规则出现在不太具体的规则之上,如果这是你的事
这是一个例子:
// scss
.card
$component: &;
padding: 2em;
&--big
padding: 2.5em;
&__value
font-size: 1.5em;
color: #000;
#$component--big &
font-size: 3em;
/* css */
.card
padding: 2em;
.card--big
padding: 2.5em;
.card__value
font-size: 1.5em;
color: #000;
.card--big .card__value
font-size: 3em;
【讨论】:
【参考方案5】:您的解决方案看起来不错,但您也可以尝试@at-root。
【讨论】:
到底是什么?我不明白为什么@at-root
可以提供帮助。【参考方案6】:
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
&__value // Is this going to work?
font-size: 3em;
您可以通过以下方式达到您想要的结果:
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big
padding: 2.5em;
.card
&__value // this would work
font-size: 3em;
【讨论】:
确实如此,但它远离了使用父选择器。尽可能多地使用它很好。【参考方案7】:通过相同的问题,我构建了一个名为 Superbem 的库,它基本上是一组 SCSS 混合,可帮助您编写 BEM 声明方式。看看:
@include block(card)
padding: 2em;
@include element(value)
font-size: 1.5em;
color: #000;
@include modifier(big)
padding: 2.5em;
@include element(value)
font-size: 3em;
给你:
.card, .card--big
padding: 2em;
.card__value
font-size: 1.5em;
color: #000;
.card--big
padding: 2.5em;
.card--big .card__value
font-size: 3em;
希望你会发现这很有用!
【讨论】:
【参考方案8】:你可以通过添加一个字符来做到这一点,不需要变量或混合。
&--big
变为 &--big &
:
.card
padding: 2em;
&__value
font-size: 1.5em;
color: #000;
&--big &
padding: 2.5em;
&__value // Is this going to work? (yes!)
font-size: 3em;
【讨论】:
这不会导致.card--big .card__value
吗?
@JakeWilson 我认为这就是问题所要求的以上是关于如何在 SASS 中使用嵌套元素构造 BEM 修改器的主要内容,如果未能解决你的问题,请参考以下文章