Understanding CSS naming conventions: BEM, OOCSS, SUIT CSS, and SMACSS
Following established CSS naming conventions can be a massive help, especially when you start building larger projects. In this article, Henry outlines several popular conventions and compares them.
Table of contents
Have you ever struggled with naming a class or element? If so, this is normal, especially for beginners in web development and those new to Cascading Style Sheets (CSS). This article gives you a better understanding of BEM, OOCSS, SUIT CSS, and SMACSS naming conventions, how they work, how to use them, and how they can help improve your CSS game.
Overview of CSS naming conventions
CSS naming conventions are guidelines that assist developers in writing consistent and understandable CSS code. These guidelines advocate utilizing specific naming patterns for CSS classes, IDs, and selectors to increase code readability, maintainability, and collaboration. Choosing the appropriate naming convention depends on the project's scope, preferences, and collaboration practices. However, adopting a consistent and well-defined naming convention can significantly improve the quality of CSS code written by developers.
Why is it helpful to use a CSS naming convention?
CSS naming conventions enhance code readability, maintainability, collaboration, scalability, and developer experience. By adopting a consistent and well-defined naming convention, developers can create more accessible CSS code to understand, maintain, and collaborate, leading to more efficient and effective web development practices. Popular CSS naming conventions include BEM (Block Element Modifier), OOCSS (Object-Oriented CSS), SUIT CSS, and SMACSS (Scalable and Modular Architecture for CSS). Choosing or creating a convention that fits your project's needs is crucial in maintaining a clean and organized codebase.
Throughout this article, we'll use the same basic code example to show how each methodology differs. A navigation component is an excellent example, as it's typically reused on multiple pages and contains child elements within. Here is our base HTML structure:
<nav> <ul> <li><a href="/about">About</a></li> <li><a href="/pricing">Pricing</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav>
Established naming conventions
When using CSS, you can implement good CSS naming conventions to make your code more readable, maintainable, and collaborative, leading to a more efficient and effective development process. You can do this by picking any of the CSS naming conventions and sticking to them. Now, we will look at BEM, OOCSS, SUIT CSS, and SMACSS individually to understand how to implement them.
BEM (Block Element Modifier)
BEM is a popular naming convention for CSS classes that helps developers create maintainable, reusable, and self-documenting code. It is based on the concept of dividing user interfaces into independent blocks, each of which can have elements and modifiers. Just as the name implies, BEM is made up of Blocks, Elements, and Modifiers.
First, let's take a look at how the base HTML structure might look using the BEM methodology before we talk through each principle:
<nav class="nav"> <ul class="nav__list"> <li class="nav__item nav__item--active"> <a href="/about" class="nav__link">About</a> </li> <li class="nav__item"> <a href="/pricing" class="nav__link">Pricing</a> </li> <li class="nav__item"> <a href="/contact" class="nav__link">Contact</a> </li> </ul> </nav>
Block
Blocks are the main components of a user interface. Each represents a standalone entity or "block" on the page, which is independent and reusable. They can have elements and modifiers of their own. Named using a lowercase string, hyphenated if multiple words (e.g., header
, menu
). The block in the example above would be the .nav
element. It is the encapsulated block that can be reused across different pages.
Element
Elements are semantically linked to the block and have no standalone meaning. They are not independent and must be associated with a block. The block's name always precedes them. They are named using a double underscore (__
) followed by the element name (e.g., header__logo
, menu__item
). In the example above, the .nav__list
, .nav__item
, and .nav__link
are all considered elements. They have no meaning beyond the context of being children of the .nav
.
Modifier
Modifiers are variations of blocks or elements. They are used to change the appearance or behavior. They represent a different version of a block or element that doesn't affect the existing block or element. They can be named using a double dash (--
) followed by the modifier name (e.g., menu__item--selected
). In the example above, the .nav__item--active
class is the modifier. Consider that your navigation items display a different "active" state if the user is on that page. This modifier might add some styles, like an underline, to signify that this is the current page.
BEM is a powerful tool that can help developers write better CSS code. It is especially well-suited for large projects with multiple developers. BEM seeks to make class names recognizable at a glance and identify where the element can be used and its relationship to other elements. It also easily shows when an element is a descendant of a particular class, which gives us more clarity as we write our CSS.
OOCSS (Object-Oriented CSS)
OOCSS is a CSS methodology that promotes modularity, reusability, and separation of concerns. It advocates treating CSS classes as objects, encapsulating their styles and properties, and using them to compose user interfaces. OOCSS operates on two main rules: 1) Separation of structure and skin and 2) Separation of container and content. Let's take a look at what that means.
Separation of structure and skin
Separation of structure and skin is a fundamental principle of OOCSS that emphasizes the distinction between CSS's structural and presentational aspects. This separation promotes modularity, reusability, and maintainability in CSS code. Structure in this context defines the layout, positioning, and behavior of elements on the page from their height, width, etc. They govern the fundamental arrangement and organization of the UI components without focusing on their visual appearance. Conversely, skin deals with the visual aspects of elements, such as colors, fonts, borders, and background properties. They control how elements look and feel, creating the desired aesthetic for the UI.
Separation of container and content
Separating container and content is another crucial principle of OOCSS, emphasizing the distinction between the containers that hold content and the content itself. In layperson's terms, this implies you should avoid using child selectors. When customizing unique page elements, such as anchor links, headers, blockquotes, or unordered lists, use unique classes rather than descendent selectors.
Let's take a look at how the base HTML structure above might look using OOCSS:
<nav class="nav"> <ul class="list nav-list"> <li class="list-item nav-item"> <a href="/about" class="link nav-link">About</a> </li> <li class="list-item nav-item"> <a href="/pricing" class="link nav-link">Pricing</a> </li> <li class="list-item nav-item"> <a href="/contact" class="link nav-link">Contact</a> </li> </ul> </nav>
As mentioned above, OOCSS aims to separate structure from skin and container from content. This means creating reusable "objects" with generic class names that define visual patterns.
Here is a breakdown of the OOCSS approach highlighted above:
.nav
represents the specific navigation component..list
and.list-item
are generic reusable classes representing a list structure that can be used anywhere..link
is a generic class for styling links that can be reused across the site..nav-list
,.nav-item
and.nav-link
are specific classes used to extend and customize the generic list and link classes for the navigation context.
The generic classes (.list
, .list-item
, .link
) define the base structural styles that can be reused, while the specific classes (.nav
, .nav-list
, .nav-item
, .nav-link
) build on top to customize for the particular component.
This separation of concerns allows for greater reuse of CSS and more maintainable code. The generic "objects" can be styled and extended in different contexts without needing to rewrite core CSS patterns each time.
SUIT CSS
SUIT CSS is a reliable and testable styling methodology for component-based UI development. It emphasizes the separation of concerns, promotes reusability, and facilitates maintainable CSS codebases. It mainly focuses on supporting UI component-based web application development, such as React.
The naming convention follows this pattern:
ComponentName
: Written in PascalCase. Identifies the specific UI component, such as button, input, or card.ComponentName--modifierName
: Represents a variation or modification of the component, such as primary, secondary, or large.ComponentName-descendentName
: Descendent name is written in camelCase. Represents a child element of the component.ComponentName.is-stateOfComponent
: Indicates the visual state of the component, such as.is-active
or.is-selected
.
Let's see how our base HTML structure might look using SUIT CSS:
<nav class="Nav"> <ul class="Nav-list"> <li class="Nav-item"> <a href="/about" class="Nav-link">About</a> </li> <li class="Nav-item"> <a href="/pricing" class="Nav-link">Pricing</a> </li> <li class="Nav-item"> <a href="/contact" class="Nav-link">Contact</a> </li> </ul> </nav>
In the example above:
.Nav
is the component name. It's written in PascalCase..Nav-list
,.Nav-item
, and.Nav-link
are descendent names. They are separated from the component name by a single hyphen (-
).- If we were to add modifiers, they would be separated from the component name by two hyphens (
--
), e.g.,.Nav--primary
. - If we were to add states, they would be written in camelCase and separated from the component name by a single dot (
.
), e.g.,.Nav-link.is-active
.
Overall, SUIT CSS brings a systematic, modular approach to authoring CSS at scale. While it requires some learning and adaptation, it can lead to more maintainable, scalable, and teamwork-friendly stylesheets in large projects.
SMACSS (Scalable Modular Architecture for CSS)
Although not a naming convention in the same way as the others mentioned above, SMACSS is a methodology used to organize and write CSS code in a more maintainable and reusable way. It promotes modularity, separation of concerns, and consistency, making managing and customizing large CSS codebases easier and can be used alongside any naming convention outlined above. Jonathan Snook created it and emphasized a modular approach to organizing stylesheets, making them more scalable and easier to manage in larger web projects. SMACSS consists of five fundamental principles, which include:
-
Base: This contains universal styles that apply to all elements on the page, such as resets, global fonts, and basic formatting. Base rules provide a consistent foundation for the entire project.
-
Layout: Defines the overall layout of the page, including grids, columns, and spacing. They often correspond to major sections of the HTML document.
-
Module: This encapsulates styles for specific UI components, such as buttons, forms, or navigation menus. It focuses on small, reusable components or modules.
-
State: Controls the visual appearance of elements based on their state, such as hover, focus, or active states.
-
Theme: This contains skin styles that apply specific color palettes, typography, and branding guidelines, allowing easy theming and customization.
SMACSS focuses on CSS architecture, so the HTML classes are less important for this example. But let's say we have the following HTML:
<nav class="nav"> <ul class="nav-list"> <li class="nav-item"> <a href="/about" class="nav-link">About</a> </li> <li class="nav-item"> <a href="/pricing" class="nav-link">Pricing</a> </li> <li class="nav-item"> <a href="/contact" class="nav-link">Contact</a> </li> </ul> </nav>
The separation of the varying styles using the SMACSS methodology might be as follows:
/* base.css */
body {
font-family: Arial, sans-serif;
}
a {
text-decoration: none;
}
/* layout.css */
.nav {
background-color: #f0f0f0;
}
.nav-list {
list-style: none;
padding: 0;
}
.nav-item {
display: inline-block;
}
/* module.css */
.nav-link {
display: block;
padding: 10px 20px;
color: #333;
}
.nav-link:hover {
background-color: #ddd;
}
/* state.css */
.nav-link.is-active {
font-weight: bold;
color: #000;
}
In the example above:
base.css
contains the default styles for the body and anchor elements.layout.css
contains styles for the navigation layout, such as background color and list styling.module.css
contains styles for the navigation items and links, which are the reusable parts of the navigation.state.css
contains a state class (.is-active
) that can be applied to a navigation link to indicate the current page.
Separating the CSS into these categories and files makes the styles more modular, easier to maintain, and less prone to specificity issues. This architecture promotes code reuse and scalability as the project grows.
Benefits of clear and meaningful names
One fundamental principle of writing maintainable and scalable CSS code is choosing clear and meaningful names for your selectors. A well-thought-out naming convention makes your code more readable and contributes significantly to your project's long-term maintainability. By sticking to a naming convention you:
- Reveal intent: Clear names provide an immediate understanding of the intended purpose.
- Increase readability and understanding: Naming conventions enhance code readability. Anyone working with the codebase, including future developers, can quickly identify and comprehend the styling applied to primary buttons.
- Improve code consistency: Consistency in naming conventions across your codebase simplifies collaboration and maintenance. Developers can easily predict and reuse class names, helping teams move faster.
Conclusion
Having a strategy for naming your classes can have a huge impact on how your codebase scales as the project size increases. Following established conventions help developers get on the same page faster, and can reduce the number of issues that arise.
Select a convention, such as BEM, OOCSS, or SUIT CSS, and establish clear, consistent guidelines for yourself and your team. Make your class names meaningful rather than obscure, and organize them logically to represent a component hierarchy. Use tools such as preprocessors and linters alongside a file architecture like SMACSS to help organize and improve code quality. Remember that your CSS code isn't just for you; it's also for anyone else who might need to read it later. Invest time in learning good naming techniques, and you will take your CSS skills to the next level.
Now that you know the basics of a few different approaches, why not try them out on a project? Here are some Frontend Mentor challenges that would work well to practice implementing CSS naming conventions:
- Social links profile: A simple UI that provides an excellent project to experiment with each approach.
- Social proof section: The challenge has a more complex UI with multiple repeated components, so it is a good step up from the previous one.
- Officelite coming soon site: If you really want to push yourself, this two-page challenge will provide a great skill test.
Practice building projects like a pro
- Portfolio-ready projects
- Professional design files
- Curate your profile
- Unlimited solution refinement