[英]How to structure BEM modifiers with nested elements in SASS
在大多数情况下,SASS + BEM 几乎是天作之合,但我的一个共同难题是了解如何在使用 SASS 父选择器时在影响其子元素的元素上最好地定义 BEM 修饰符。
我使用 BEM 样式语法在 SASS 中定义了以下组件:
.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;
}
}
}
这很好用。 但是将元素定义为变量似乎有点愚蠢。 也许这是做到这一点的唯一真正方法......我不确定。 是否有更好的选择来构建它?
为什么不这样做呢?
.card {
padding: 2em;
&__value {
font-size: 1.5em;
color: #000;
}
&--big {
padding: 2.5em;
}
&--big &__value {
font-size: 3em;
}
}
我刚刚找到了一种用 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 的文章。 感谢谢尔盖·科瓦连科
您可以将修饰符拆分为不同的结构,但嵌套在.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;
}
我认为这是一种近乎完美的方式,虽然它不是完美的嵌套我希望这是一个帮助!
您可以在此处使用另一种模式。
这会:
- 将实际的卡片修饰符与其元素的修饰符分开
- 将修改后的样式保留在相同元素的选择器中,因此您无需上下滚动代码即可查看正在修改的内容
- 将防止更具体的规则出现在不太具体的规则之上,如果那是你的事
下面是一个例子:
// 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;
}
您的解决方案看起来不错,但您也可以尝试@at-root 。
.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;
}
}
}
}
在经历同样的问题时,我构建了一个名为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;
}
希望你会发现这很有用!
你可以通过添加一个字符来做到这一点,不需要变量或混合。
&--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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.