CSS - BEM Naming
This note is about BEM CSS class naming methology.
BEM stands for Block Element Modifier. These three parts make up each class name.
Blocks contain elements. Class names start with a block definition and may optionally have one or multiple element definitions. Blocks and elements are separated by double underscores __
.
.block {} /* Component, a well defined visual context. */
.block__element {} /* A descendent element of a component. */
.block__element__element {} /* A descendent element of an element. */
Each block and element may have one modifier. Modifiers are separated with double dashes --
. Having multiple modifiers for a single block or element is not allowed.
.block--modifier {} /* Component has multiple states. */
.block--modifier__element {} /* Component state affects child elements. */
.block__element--modifier {} /* Child elements have multiple states. */
.block__element--modifier__element {} /* You get the idea. */
Block, element and modifier names are in dashed lower case.
.person-profile {}
.person-profile--male {}
.person-profile--female {}
.person-profile__hand {} /* Profile has a hand element. */
.person-profile--female__hand {} /* Female hand has a special visual. */
.person-profile__hand--left {} /* Left hand has a special visual. */
BEM takes more time to write, but helps future development. When naming classes like this, you understand how classes are related by reading the class names in the HTML.
<form class="site-search site-search--full">
<input type="text" class="site-search__field">
<input type="Submit" value ="Search" class="site-search__button">
</form>
You can mix standalone rules with BEM. Standalone rules should be written so that they work in all contexts (blocks).
.baseline-top { margin-top: 10px; }
.baseline-bottom { margin-bottom: 10px; }
js-*
classes shouldn't have any visual style. All JavaScript hook CSS classes start with js-
and shouldn't have any definition in the CSS files. They are only meant to be used by JavaScript. Also, JavaScript shouldn't search for any DOM elements without targeting the js-
prefix, but may add and remove any classes.
<!-- Find this DOM element with '.js-date-select', never `.date-select` -->
<div class="js-date-select date-select"></div>
<!-- Manipulating classes in JavaScript is ok. -->
<div class="js-date-select date-select date-select--highlight"></div>