- modularity
- encapsulation
- predictability
- extensibility
- integrability
- explicitness
- readability
- practicality
- maintainability
- semantic
- SMACSS introduces modularity
- modules encapsulates semantic elements
- modules are extendable
- modularity and encapsulation enables clean integration with other elements
- modules have predictable specificity. Important for modifying styles.
- BEM introduces class naming structure
- class naming structure makes element relationships explicit
- class naming structure promotes coding standards
Encapsulation achieved through module namespacing instead of SASS nesting
.module
.module--modifier
.module__component
Base module element; defines base styles
// scss
.status
.ad-banner
// html
<div class="status"></div>
<div class="ad-banner"></div>
Modification to module/component styles
// scss
.status--alert
.status--code-red
.status__label--huge
// html
<div class="status status--alert">
<div class="status__label status__label--huge"></div>
</div>
avoid using more than 2 modifiers on an element:
-
it avoids being too presentational in the markup
<div class="status status--alert status--huge status--code-red status--rounded status--some-modifier"><div/>
-
if an element needs more than 2 modifiers,
@extend
the module to create a variant module to apply extra modifiers and custom styles to make a more semantic module
CSS cascade may be important for modifiers, as it might override module base styles. Place Module Modifier declarations below Module Base declaration.
prefix state modifiers with is-
. usually toggled by javascript.
2+ module modifier caveat does not apply to module states as it gets applied dynamically
// scss
.status--is-hidden
.status--is-selected
// html
<div class="status status--code-red status--is-hidden"></div>
children elements of a module
// scss
// module
.status
// component
.status__label
.status__start-date
.status--alert__icon
// html
<div class="status">
<div class="status__label"></div>
</div>
avoid more than 2 levels of component:
-
long class selectors can occur
.some-module__some-component__subcomponent-name__subsubcomp
-
it creates a restriction on module complexity; maintaining modularity
-
if a module requires more than 2 levels of components, create different modules for those components
When I first started writing modules like this I’d often end up with huge modules with complex class names… most child components can be extracted out into their own standalone modules. So if you leave the positioning up to the parent, we end up with smaller, standalone modules. - source
module structure on collections may look this way, but .words__word
styles could get more complicated
.words
.words__word
.words__word--modifier
.words__word__component
instead:
.words
.word
.word--modifier
.word__component
instead of using -list
, pluralize collection container: end with an s
a module inside another module
<div class="content">
<h1 class="headline"></h1>
</div>
Here, there are two circumstances for .headline
- it is styled that way because it’s in
.content
, or - whether it just happens to live in
.content
.
If it is the latter then it's a simple nesting. If it's the former then it's a complex nesting. .content
serves as the base module, while .headline
serves as the nested module
nested module that can stand on its own without any modification inside a base module
simply drop the module into the markup
// scss
.post
.advertisement
// html
<div class="post">
<div class="advertisement"></div>
</div>
nested module that needs modification in order to be styled properly inside a base module (module context styling)
@extend
nested module as a component for the base module. Use the nested module namespace for the base module component.
// scss
.sidebar__advertisement {
@extend .advertisement;
box-shadow: none;
}
// html
<div class="sidebar">
<h1 class="sidebar__advertisement"></h1>
</div>
@extend
ing the nested module will make the relationship explicit with the original module. Any modifications to the nested module are completely encapsulated in the base module.
A module should only manage its contents, and nothing outside of it: siblings and parent elements. This will ensure encapsulation completely within the module. Thus, nested module should not style when it's in a base module. Instead, the base module should style nested modules, if needed.
// BAD
.advertisement { // advertisement module
background-color: blue;
color: white;
}
.post .advertisement { // advertisement module in post module context
color: grey;
}
// GOOD
.advertisement { // advertisement module
background-color: blue;
color: white;
}
.post { // post module
padding: 10px;
}
.post__advertisement { // post component: advertisement
@extend .advertisement;
color: grey;
}
a separate module for extending or modifying base module styles or a reoccurring combination of the base module. Primarily applies to module element with more than two modifiers applied to it.
.status-modal {
@extend .status;
@extend .status--alert;
@extend .status--rounded;
@extend .status--huge;
// dead centre layout w/ flex
@include flexbox;
@include flex-direction(column);
@include justify-content(center);
@include align-items(center);
}
if a variant overrides many styles of the base module, it is essentially a completely different module. Refrain from extending the base module. Create a new module.
an extend-only module used as a scaffold for other modules and can't be used by itself e.g. grid-systems & layouts
It helps avoid presentational markup and promote sematic modules
%media-object // Nicole Sullivan's Facebook layout object
.news-feed-post {
@extend %media-object;
}
- Extending modules (variant/nested-complex modules) might make it hard to debug/read on the browser dev toolkit when many other modules/elements extended the same modules
This is an excellent guide, thanks for sharing.