CSS (Sass) Guide
Best practices for writing scalable and maintainable CSS using Sass, including the BEM methodology and Atomic Design principles.
BEM (Block, Element, Modifier) is a powerful methodology for naming CSS classes to create a more robust and understandable structure. It helps solve common CSS problems like specificity conflicts and global scope leakage by promoting modularity, reusability, and a clear structure. This makes the codebase easier for new developers to understand and contributes to a more maintainable and scalable application.
BEM class names are formed using a simple pattern: block__element--modifier. This structure clearly defines the role of each class, making the relationship between your HTML and CSS transparent.
A block is a standalone, reusable component. It's the 'B' in BEM. Think of it as a significant, independent piece of the UI like a header, sidebar, or a card component.
/* A card component is a perfect example of a block. */
.card { /* ... */ }
/* A navigation menu is another block. */
.main-nav { /* ... */ }An element is a part of a block and has no standalone meaning. It's the 'E' in BEM. Its name is formed by adding two underscores (__) to the block name. An element is semantically tied to its block.
/* An element is always part of a block. */
.card__title { /* ... */ }
.card__image { /* ... */ }
/* Elements of the navigation block. */
.main-nav__item { /* ... */ }
.main-nav__link { /* ... */ }A modifier defines a variation, state, or appearance of a block or an element. It's the 'M' in BEM. Its name is formed by adding two hyphens (--) to the block or element name. They can represent different states (like 'active' or 'disabled') or different versions (like 'primary' or 'large').
/* A modifier for the card block. */
.card--featured { /* ... */ }
/* A modifier for the navigation link element. */
.main-nav__link--active { /* ... */ }Sass's nesting capabilities make writing BEM even cleaner and more intuitive. The ampersand (&) character is used to refer to the parent selector, which makes it easy to construct BEM-style class names without repetition.
.card {
// Block styles
display: flex;
flex-direction: column;
// Modifier for the block
&--featured {
border: 2px solid gold;
}
// Element
&__title {
font-size: 1.5rem;
color: #333;
}
// Element
&__button {
// Element styles
padding: 10px 20px;
// Modifier for the element
&--disabled {
background-color: #ccc;
cursor: not-allowed;
}
}
}Atomic Design is a methodology for creating design systems. It provides a clear methodology for crafting UI in a deliberate and hierarchical manner. The five levels of Atomic Design are Atoms, Molecules, Organisms, Templates, and Pages.
Atoms are the basic UI elements and cannot be broken down any further. They serve as the foundational building blocks of our interface. Examples include labels, inputs, buttons, and individual icons.
<!-- Atom Examples -->
<button class="btn">Click me</button>
<input type="text" class="input" placeholder="Enter text">Molecules are groups of atoms bonded together to serve a single, cohesive purpose. These molecules take on their own properties and serve as the backbone of our design systems. For example, a search form molecule might be composed of a label atom, an input atom, and a button atom.
<!-- Molecule: Search Form -->
<div class="search-form">
<label class="search-form__label">Search</label>
<input type="text" class="search-form__input" placeholder="Search...">
<button class="search-form__button">Go</button>
</div>Organisms are groups of molecules and/or atoms joined together to form a relatively complex, distinct section of an interface. For example, a site header organism might include a logo atom, a navigation molecule, and a search form molecule.
<!-- Organism: Site Header -->
<header class="site-header">
<div class="site-header__logo">...</div>
<nav class="site-header__nav">...</nav>
<div class="site-header__search">...</div>
</header>Templates are page-level objects that place components into a layout and articulate the design's underlying content structure. Pages are specific instances of templates where placeholder content is replaced with real representative content, giving a concrete view of the final UI.
Atomic Design and BEM are not mutually exclusive; they work together perfectly. Atomic Design helps you structure your components conceptually (defining what constitutes an atom, molecule, or organism), while BEM provides a robust naming convention for the CSS that styles those components. An organism can be a BEM block, and its constituent parts can be BEM elements.