繁体   English   中英

如何在 SASS 中使用嵌套元素构建 BEM 修改器

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM