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;
}
}
这有效(特别是在这个简化的演示中)但是在一个更复杂的组件中有许多修饰符,这可能是一个潜在的难以维护和保持bug。此外,如果可能的话,继续使用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;
}
}
}
这很有效。但是将元素定义为变量似乎有点愚蠢。也许这是唯一真正做到这一点的方式......我不确定。是否有更好的选择来构建它?
答案 0 :(得分:4)
为什么不这样做?
.card {
padding: 2em;
&__value {
font-size: 1.5em;
color: #000;
}
&--big {
padding: 2.5em;
}
&--big &__value {
font-size: 3em;
}
}
答案 1 :(得分:1)
您可以将修改器拆分为不同的结构,但嵌套在.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;
}
我认为这是一种近乎完美的方式,尽管它并不完美嵌套 我希望这是一个帮助!
答案 2 :(得分:1)
我刚刚找到了一个更好的方法来实现这一点,通过使用变量来存储父选择器的值,您可以在任何嵌套级别使用它!
例如,我将.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
答案 3 :(得分:0)
您的解决方案看起来很不错,但您也可以尝试@at-root。
答案 4 :(得分:0)
.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;
}
}
}
}
答案 5 :(得分:0)
经历同样的问题我构建了一个名为Superbem的库,它基本上是一组SCSS mixins,可以帮助你编写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;
}
希望你能发现它有用!
答案 6 :(得分:0)
您可以在此处使用另一种模式。
这将:
-将实际的卡片修饰符与其元素的修饰符分开
-将修改后的样式保留在相同元素的选择器中,因此您无需上下滚动代码即可查看正在修改的内容
-如果您是这样的话,则会阻止更具体的规则出现在不那么具体的规则之上
这是一个例子:
// 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;
}
答案 7 :(得分:0)
您可以通过添加一个字符来实现这一点,不需要变量或混合。
&--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;
}
}
}