16

I am using BEM, and have an element with multiple modifiers:

<div class="block__element block__element--m1 block__element--m2"></div>

I'm using SCSS and taking advantage of it to write nested rules compatible with BEM. If I want to write a rule where an element (like the above) has both the m1 and m2 modifier, is there a way to write that compatible with the way I'm currently writing them? This is the kind of syntax I'm after, but results in a syntax error:

.block {
    display: block;

    &__element {
        display: inline;

        &--m1 {
            background-color: red;
        }

        &--m2 {
            background-color: green;
        }

        // Syntax error
        &--m1&--m2 {
            background-color: yellow;
        }
    }
}

I can think of ways around this by using attribute selectors, but is there a neater way?

For the record, the compiled attribute selector should be:

.block__element--m1.block__element--m2
Robert
  • 5,735
  • 3
  • 40
  • 53

2 Answers2

33

@3rdthemagical's answer did give me some inspiration for a better solution. Sass simply doesn't like & appearing after the beginning of the selector, but it doesn't mind it wrapped in #{}:

.block {
    display: block;

    &__element {
        display: inline;

        &--m1 {
            background-color: red;
        }

        &--m2 {
            background-color: green;
        }

        // Correct!
        &--m1#{&}--m2 {
            background-color: yellow;
        }
    }
}
Robert
  • 5,735
  • 3
  • 40
  • 53
1

Store selector names in variables. Sassmeister demo.

.block {
  $module: ".block";

  &__element {
    $this: "#{$module}__element";

    &--m1#{$this}--m2 {
        background-color: yellow;
    }
  }
}

Generated css:

.block__element--m1.block__element--m2 {
  background-color: yellow;
}
3rdthemagical
  • 5,271
  • 18
  • 36
  • I was hoping Sass would provide better solutions than this—having to store the selectors in variables as well means I'm having to repeat myself, and Sass's biggest selling point for me is that it helps me avoid just that! – Robert Dec 05 '17 at 12:37
  • 1
    You did give me inspiration for a correct answer, however! https://stackoverflow.com/a/47653943/376683 – Robert Dec 05 '17 at 12:44
  • 1
    You can avoid repeating yourself using the & operator, which as discussed above just inserts the text of the selector so far: `.block { $module: &; }` will be equivalent to `.block { $module: ".block"; }` – snazzybouche Sep 05 '22 at 07:07