8

我可以以某种方式重构以下代码片段以摆脱双重修饰符声明吗?

.block {
  &__element {
    rule: value;
  }
  &--modifier {
    rule: value;
  }
  &--modifier & {
    &__element {
      rule: value;
    }
  }
}

想要的输出:

.block {
   property: value;
}
.block--modifier {
  property: value;
}
.block--modifier .block__element {
  property: value;
}
4

4 回答 4

13

在修饰符内嵌套元素是一个已知问题。有很多解决方法。

可变方式

将块元素存储在变量中。

并在修改器内创建元素时使用它进行插值。

.block {
  $block: &;

  &__element {
    property: value;
  }

  &--modifier {
    property: value;
    #{$block}__element {
      property: value;
    }
  }
}

请参阅下面的输出。

功能方式

1. 创建一个返回块元素的函数。

它将获取父选择器并剪切之前的单词--(即块)。看起来很hacky,但这是最简单的方法。

@function block() {
  $selector: str-slice(inspect(&), 2, -2);
  $index: str-index($selector, '--') - 1;
  @return str-slice($selector, 0, $index);
}

2. 使用内插函数。

这将返回块的名称,因此您不必重复它。

.block {
  property: value;

   &--modifier {
     property: value;
     #{block()}__element {
       property: value;
     }
   }
}

请参阅下面的输出。

两种方式都将输出到:

.block {
  property: value;
}

.block--modifier {
  property: value;
}

.block--modifier .block__element {
  property: value;
}
于 2015-08-20T01:40:23.633 回答
1

您可以像这样将块放置在&--modifier选择器中,使用块的类名而不是&定位它。

.block {
  &__element {
    rule: value;
  }
  &--modifier {
    rule: value;

    .block {
      &__element {
        rule: value;
      }
    }
  }
}

但是,这可能不是最好的 BEM 解决方案,您应该考虑将嵌套块重命名为包含块的元素,例如.block__another-element或完全创建一个新块。

于 2015-08-18T09:03:24.373 回答
1

您可以&在修饰符旁边添加类似于 Toni 的解决方案。

.block {

  &__element {
    rule: value;
  }

  &--modifier & {
    rule: value;
    
    &__element {
      rule: value;
    }
  }
}

然而,这需要.block是一个根选择器,而不是嵌套在任何其他选择器中。

只是另一种可能的解决方案。不过,对于大多数情况,我仍然更喜欢 Toni 的解决方案。

于 2018-01-16T14:04:47.803 回答
1

如果有人少用,这将对您有所帮助!

@block:.parent;
@{block}{
    backgroung:red;
    &--modifier{
        backgroung:blue;
    }
    &__child{
        font-size:20px;
        @{block}--modifier & {
           font-size:40px;
        }
    }
}
于 2018-08-14T15:54:15.963 回答