Choosing What to Name Things in CSS

When choosing class-name selectors, use semantic class names.

When we use the word semantic, we mean meaningful. Class names should describe what the rule does or the type of content it affects. Ideally, we want names that will endure changes in the design requirements. Naming things is harder than it looks.

Here are examples of what not to do: .red-text , .bLue-button , .border-4px , .margin10px . What’s wrong with these? They’re too tightly coupled to the existing design choices. Using cLass=”red-text” to mark up an error message does work. But what happens if the design changes and error messages become black text inside orange boxes? Now your class name is inaccurate, making it tougher for you and your colleagues to understand what’s happening in the code.

A better choice in this case is to use a class name such as .alert , .error , or .message- error . These names indicate how the class should be used and the kind of content (error messages) they affect.

We’ll now look at two methodologies for naming things in CSS. Both methods were created to improve the development process for large sites and large teams, but they work just as well for teams of one. It’s up to you whether you choose one or the other, neither, or a mix of both. The point of introducing them is to help you to think through approaches for writing your own CSS.

1. Block-Element-Modifier (BEM)

BEM , or Block-Element-Modifier, is a methodology, a naming system, and a suite of related tools. Created at Yandex , BEM was designed for rapid development by sizable development teams. In this section, we’ll focus on the concept and the naming system.

BEM methodology encourages designers and developers to think of a website as a collection of reusable component blocks that can be mixed and matched to create interfaces. A block is simply a section of a document, such as a header, footer, or sidebar, as illustrated below.

Perhaps confusingly, “block” here refers to the segments of HTML that make up a page or application.

Blocks can contain other blocks. For example, a header block might also contain logo, navigation, and search form blocks, as seen below. A footer block might contain a site map block. [3] [4]

More granular than a block is an element. As the BEM documentation explains17:

An element is a part of a block that performs a certain function. Elements are context-dependent: they only make sense in the context of the block they belong to.

A search form block, for example, contains a text input element and a submit button element, as illustrated below. (To clarify, we’re using “element” as a shorthand for “design element” rather than in the sense of HTML elements.)

A main content block, on the other hand, might have an article list block. This article list block might contain a series of article promo blocks. And each article promo block might contain image, excerpt, and “Read more” elements, as presented below.

Together, blocks and elements form the basis of the BEM naming convention. According to the rules of BEM:

  • block names must be unique within a project
  • element names must be unique within a block
  • variations of a block-such as a search box with a dark background-should add a modifier to the class name

In a BEM naming system, block and element names are separated by a double underscore (as in .block__ element). Block and element names are separated from modifier names by a double hyphen (for example, .bLock–modifier or .block____ eLement–modifier ).

Here’s what BEM looks like using a search form example:

<form class=”search”>

<div class=”search_____ wrapper”>

<label for=”s” class=”search_______ label”>Search for: </label>

<input type=”text” id=”s” class=”search_________ input”>

<button type=”submit” class=”search________ submit”>Search</button>

</div>

</form>

A variation of this form with a dark background might use the following markup:

<form class=”search search–inverse”>

<div class=”search_wrapper search_wrapper–inverse”>

<label for=”s” class=”search_label search_label–inverse”>Search for: </label>

<input type=”text” id=”s” class=”search_input search_input–inverse”>

<button type=”submit” class=”search_submit search_submit–inverse”>Search</button>

</div>

</form>

Our CSS might look like this:

.search {

color: #333;

}

.search–inverse {

color: #fff;

background: #333;

}

.search__ submit {

background: #333;

border: 0;

color: #fff;

height: 2rem;

display: inline-block;

}

.search__ submit–inverse {

color: #333;

background: #ccc;

}

In both our markup and CSS, search–inverse and search_ LabeL–inverse are additional class names. They’re not replacements for search and search_Label . Class names are the only type of selector used in a BEM system. Child and descendant selectors may be used, but descendants should also be class names. Element and ID selectors are verboten. Enforcing block and element name uniqueness also prevents naming collisions, which can become a problem among teams.

There are several advantages to this approach:

  • it’s easy for new team members to read the markup and CSS, and understand its behavior
  • adding more developers increases team productivity
  • consistent naming reduces the possibility of class-name collisions and side effects
  • the CSS is independent of the markup
  • the CSS is highly reusable

Source: Brown Tiffany B (2021), CSS , SitePoint; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *