Sass Throws an Error for Bem Syntax

Sass 3.3 new feature @at-root doesn't seem to compile

I believe you are using a slightly out of date version of the syntax. Try this:

@mixin element($name)
{
@at-root &__#{$name}
{
@content;
}
}

Issue with M in BEM with React CSS Module

The way you using modifiers is incorrect at all.

Modifiers are not sub-elements, they are modifiers for blocks and elements and can't be used without mother-eneities.

Correct:

  • <div class="b">
  • <div class="b__e">
  • <div class="b b--m1 b--m2">
  • <div class="b__e b__e--m b__e--m2">

Incorrect:

  • <div class="b--m1">
  • <div class="b__e--m">

The reason why it works like this is the nature of modifiers — they are things very close to interfaces or mix-ins, they can't be used without blocks like interfaces can't be used without classes.

Read more about modifiers here: https://en.bem.info/methodology/key-concepts/#modifier

Another thing you should not repeat BEM-structure in your HTML-structure.

So this is Incorrect:

<div className={styles.card__content}>
<div className={styles['card__content--icn']}>Icon</div>
<div className={styles['card__content--sub']}>Test</div>
</div>

And this is Correct:

<div className={styles.card__content}>
<div className={styles.card__icon}>Icon</div>
<div className={styles.card__sub}>Test</div>
</div>

See https://en.bem.info/methodology/faq/#can-i-create-elements-of-elements-block__elem1__elem2


If you interesting in using BEM with React you should take a look at bem-react-core — tiny library that helps you generating BEM-classes, provides runtime, etc.:

  • https://github.com/bem/bem-react-core/

:deep() syntax with nested scss rules

Sass apparently doesn't allow the selector argument list of :deep(or of any other pseudo-class) to be nested because of the reason you mentioned, but there are a couple workarounds.

Workaround 1: Split up the Sass styles

Split up the styles so that :deep's selector list is not nested:

<!-- MyParent.vue -->
<style scoped lang="scss">
:deep(.wrapper) {
display: flex;
}
:deep(.wrapper__element) {
display: block;
}
</style>

demo 1

Workaround 2: Split up the class names

Break up the BEM class names (from wrapper__element to __element) so that parent selectors are not necessary:

<!-- MyComponent.vue -->
<template>
<div class="wrapper">
<div class="__element">...</div>
</div>
</template>

or augment wrapper__element with an additional __element class (if you can ignore the repetition):

<!-- MyComponent.vue -->
<template>
<div class="wrapper">
<div class="wrapper__element __element">...</div>
</div>
</template>

For some reason, this scenario requires :deep to based on a selector (e.g., root in the example below):

<!-- MyParent.vue -->
<template>
<div class="root">
<MyComponent />
</div>
</template>

<style scoped lang="scss">
.root:deep(.wrapper) {
display: flex;

.__element {
display: block;
}
}
</style>
<!-- MyComponent.vue -->
<template>
<div class="wrapper">
<h1>.wrapper</h1>

<!-- Add __element class here (and optionally remove wrapper__element) -->
<div class="wrapper__element __element">
<h1>.wrapper__element</h1>
</div>
</div>
</template>

demo 2

Sass .scss: Nesting and multiple classes?

You can use the parent selector reference &, it will be replaced by the parent selector after compilation:

For your example:

.container {
background:red;
&.desc{
background:blue;
}
}

/* compiles to: */
.container {
background: red;
}
.container.desc {
background: blue;
}

The & will completely resolve, so if your parent selector is nested itself, the nesting will be resolved before replacing the &.

This notation is most often used to write pseudo-elements and -classes:

.element{
&:hover{ ... }
&:nth-child(1){ ... }
}

However, you can place the & at virtually any position you like*, so the following is possible too:

.container {
background:red;
#id &{
background:blue;
}
}

/* compiles to: */
.container {
background: red;
}
#id .container {
background: blue;
}

However be aware, that this somehow breaks your nesting structure and thus may increase the effort of finding a specific rule in your stylesheet.

*: No other characters than whitespaces are allowed in front of the &. So you cannot do a direct concatenation of selector+& - #id& would throw an error.



Related Topics



Leave a reply



Submit