Naming
There are only two hard problems in Computer Science: cache invalidation and naming things. Phil Karlton, Netscape
Naming things is harder.
Methodologies
There are many ways to name and structure CSS:
- No standard (most common) — It all sort of happens at once
- OOCSS — Object-Oriented CSS
- BEM — Block, Element, Modifier
- SMACSS — Scalable and Modular Architecture for CSS
- SUIT CSS — Custom processor and framework
- Maintainable CSS — BEM but with camel casing
- Inuit CSS — No UI, just structural framework
- Atomic CSS — CSS replacement for component-based frameworks (monstrosity)
- Tailwind CSS — Everything is a utility class (bleeding eyes)
None of these are perfect. They copy, overlap, underlap, and contradict each other. Understand that each framework was created to support a particular kind of application and different development practices.
Picking one misses the point. Study and learn from them.
TODO
Even within BEM-like naming systems there are variations: Fifty Shades of BEM.
TODO - Read: https://en.bem.info/forum/4/
The GravDept methodology
GravDept treats almost everything as:
- BEM components
- Utility classes
This blend works for us because our projects have similar characteristics:
- Responsive design and mobile-first thinking are suited to creating components before layouts.
- Some projects write HTML from scratch.
- Some projects inherit HTML from frameworks (ex: Magento).
- We don’t publish a monolithic design system (ex: Bootstrap, Salesforce Lightning) that other applications inherit and modify.
- We do share architecture and copy components across projects for efficiency.
BEM provides a naming schema that’s flexible where needed:
- Modularize class names so they’re extensible.
- Decouple CSS from HTML (to a degree).
The BEM methodology is a better way to decouple CSS from HTML, and modularize class names so they can be extended.
Naming problems that matter
Use prefix-free naming
Some methodologies make rigid distinctions (enforced with class prefixes) between layouts, modules, components, and utilities. Example:
// Layout
.l-header {}
.l-matter {}
.l-footer {}
.l-grid {}
// Component
.c-callout {}
.c-form {}
// Utility
.u-align-center {}
.u-m-b-1 {}
.u-text-xl {}
We haven’t found that necessary.
Utilities are always self-documenting and descriptive. They rarely collide with component names. Everything else works as a BEM component if you treat it that way.
// Layout
.app-header {}
.app-matter {}
.app-footer {}
// Component
.callout {}
.grid {}
.form {}
// Utility
.align-center {}
.m-b-1 {}
.text-xl {}
Our filesystem uses folders for organization, but class naming doesn’t need to reflect this. It’s overkill.
This also smooths out
<div class="align--center text--xl m-b-1">
Hello World!
</div>
Everything else works as a BEM component.
Starting out, if everything as a component, and it works fine.
Modifiers vs. utilities
x
BEM naming
GravDept BEM uses one underscore. Default BEM uses two underscores, which serves no purpose.
Why it’s better
- Every selector has the same specificity (1) because each selector is one class.
- Every element is defined via a block.
- Every modifier is defined via a block or element.
- Every class imparts some structural info without binding to exact HTML.
<div class="block block--modifier">
<div class="block_element block_element--modifier">
Hello
</div>
</div>
// BEM (default)
.block
.block__element {}
.block--modifier {}
.block__element--modifier {}
// BEM (GravDept)
.block {}
.block_element {}
.block--modifier {}
.block_element--modifier {}
Example
<div class="panel panel--collapsible">
<div class="panel_header">
<h1>Heading</h1>
</div>
<div class="panel_body">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
.panel {} // Block
.panel--collapsible {} // Block modifier
.panel_header {} // Element
.panel_body {} // Element
.panel_body--unpadded {} // Element modifier
Why it’s better
- All the selectors have same specificity (one).
- Every element is defined via a block.
- Every modifier is defined via a block or element.
- Each class name imparts structural info without binding to exact HTML.
Element suffixes
Always use suffixes with these elements:
.some-button {}
.some-form {}
.some-grid {}
.some-input {}
.some-link {}
.some-list {}
.some-table {}
Plurals and singulars
Prefer writing singular nouns:
.card {}
Prefer writing plural nouns to group sets of singular nouns:
<div class="cards">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>