Sass BEM: избегайте дублирования модификатора, когда элемент находится внутри модификатора

можно ли как-то отрефакторить следующий фрагмент кода, чтобы избавиться от объявление двойного модификатора?

.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 ответов


вложенность элементов внутри модификаторов-это известная проблема. Есть много обходных путей.

переменной способом

сохраните элемент блока в переменной.

и используйте его интерполированным при создании элемента внутри модификатора.

.block {
  $block: &;

  &__element {
    property: value;
  }

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

см. Вывод ниже.

функции как

1. Создайте функцию, возвращающую элемент block.

он получит родителя селектор и вырезать слово перед -- (это блок). Выглядит банально, но это самый простой способ.

@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;
}

вы можете поместить блок в &--modifier селектор, как это, используя имя класса блока, а не & таргетинг.

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

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

однако это, возможно, не лучшее решение BEM, вы должны рассмотреть переименование вложенного блока в качестве элемента содержащего блока, такого как .block__another-element или создание нового блока полностью.


вы могли бы добавить & рядом с модификатором для решения, подобного решению Тони.

.block {

  &__element {
    rule: value;
  }

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

это, однако, потребует .block быть корневым селектором, а не вложенным в любой другой селектор.

еще одно возможное решение. Однако в большинстве ситуаций я все равно предпочел бы решение Тони.


если кто-то использует меньше, это поможет вам!

@block:.parent;
@{block}{
    backgroung:red;
    &--modifier{
        backgroung:blue;
    }
    &__child{
        font-size:20px;
        @{block}--modifier & {
           font-size:40px;
        }
    }
}