EDIT :
Since asking this question, not only have I realized that there can only be one modifier per modifier class, but I've also found out that the BEM website itself recommends using extra classes for modifiers, so I've officially adopted that method instead.
I've been using SASS with BEM for a little bit, and I'd like to know what are the pros and cons of using multiple classes for modifiers vs @extend
-ing the respective block/element class. Is there one that's generally favored over the other ? (considering I won'be be including classes across @media
queries [should it even mater ?])
Example of multiple classes :
<div class="btn btn--admin btn--primary">
VS
Example of @extend
-ing :
.btn {
// ...
}
.btn--admin {
@extend .btn
// ...
}
.btn--primary {
@extend .btn
// ...
}
Edit I didn’t get the point of the question at first. After the explanation, here goes my answer.
The result is the same, but using multiple classes for modifiers gives a more granular control in a non-css compilation or edition way (you can change element properties without having to re-compile the sass code or edit your css). Also it will provide a more verbose reading of the html code. By reading btn btn-primary disabled
you will know, without having to use the inspector o going to the css code, that you have a button, with a btn-primary
style and that the button is disabled
. You can get more information there than on a single class button
extending the rest of the classes. This is a more suitable approach if someone else is going to use your code or work on your project/website or to build an easy to use framework for example.
If it’s just for a small project/website with minor maintenance/update, using the extends will be a good option too. Sometimes there is no need to fill up the html with lots of classes for each element.
The first approach will result in a smaller css and more verbose html. The second option will increase you css size while creating a more “abstract” code reading.
Using multiple classes is more scope dependent that extending a base class or even a non populated extend (defined as %myextend { ... }
.
Consider de following scenario: you have several classes and all share some properties at a different nesting levels (or scope) and event thru different breakpoints. Using multiple class definition will require a lot of code and exceptions to be able to group all the classes together and will require you to duplicate the code (in case of sharing the same code across multiple media queries).
.base,
.parent .another,
.more-clases {
// shared properties
}
@media (your-query) {
.specific-query-class {
//shared properties (repeated)
}
}
In that case you won’t be able to group all your classes definitions in one single definition scope as you could do using @extend
:
%my-extend {
// shared properties
}
.base,
.parent .another,
.more-clases {
@extend %my-extend;
}
@media (your-query) {
.specific-query-class {
@extend %my-extend;
}
}
That will allow to share/group properties blocks across different nesting levels and media queries definitions without repeating your code blocks.
Defining the extend with %
instead of .
will allow to share the properties block between different nesting levels and media queries definitions. The main definition of the extend won’t be compiled to css: the definition block will be copied to all the extended rules. Using .
for the definition will output the mail properties block to css and will group all the extended classes together, but with this type of extend you can extend thru different media queries.
Hope it helps.