BEM with SASS and :hover

so4t picture so4t · Dec 1, 2015 · Viewed 11.5k times · Source

What's the proper way of declaring active/focus/hover states using BEM with SASS? For example, I have this structure:

<div class="card">
    <img class="card__image" src="..." alt="">
    <div class="card__overlay">
        <div class="card__title"></div>
    </div>
</div>    

And the SCSS:

.card {
   &__image {
   }

   &__overlay {
   }

   &__title {
   }
}

And I want to modify the elements when hovering on the block. This doesn't work:

.card {
   &__overlay {
       display: none;
   }

   &:hover {
       &__overlay {
           display: block;
       }
   }
}

And having to write the whole .project__image just for this one instance seems wrong.

Is there any other way to accomplish this?

Answer

aaronmarruk picture aaronmarruk · Nov 7, 2016

You can achieve the desired result using the Sass ampersand selector, without using variables or interpolation.

Referencing parent selectors by using the ampersand (&) can be a powerful tool, if used right. There are simple uses of this feature as well as some very complex uses of this feature.

For example:

.card { 

    &__overlay {
        display:none;
    }

    &:hover & {
        &__overlay  {
            display: block;
        }   
    }
}

Results in:

.card__overlay {
    display: none;
}

.card:hover .card__overlay {
    display: block;
}

This code uses fewer language constructs (e.g. no use of variables or interpolation) and so is arguably a cleaner implementation.