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>