Perhaps you’ve heard this one before?
There are only two hard things in Computer Science: cache invalidation and naming things.
– Phil Karlton
Well, as any developer that writes code daily could attest those words are very true; and CSS class naming and assignment is no exception. Let’s discuss some of the reasons why and some of the solutions and theories offered to help mitigate this conundrum. But first, let’s try and clear the air around one particular subject: semantics.
Semantics is the study of symbols, words, phrases and signs and their meaning, both philosophically and linguistically.
In the context of front-end web development, semantics are largely concerned with the agreed meaning of HTML elements, attributes, and attribute values (including extensions like Microdata). These agreed semantics, which are usually formalised in specifications, can be used to help programmes (and subsequently humans) better understand aspects of the information on a website. However, even after formalisation, the semantics of elements, attributes, and attribute values are subject to adaptation and co-option by developers. This can lead to subsequent modifications of the formally agreed semantics (and is an HTML design principle).
“About HTML semantics and front-end architecture” – Nicolas Gallagher
As front-end developers, we tend to toss around the word semantics a lot. We want our code to be semantic, but what do we mean?
There are certain fallacies in regards to CSS and HTML semantics. Yes, HTML can have semantic purpose and help browsers render proper markup to end-users. However, CSS has no semantics; and if it does, it is merely cultural, internal, agreed-upon semantics. In other words, to say certain classes or class naming conventions are “unsemantic” is moot. You’re merely stating that the class names don’t make sense (lack meaning) to you. For the most part, any class name has meaning and purpose to somebody.
The main purpose of class naming should be to help developers. If your HTML is outlined properly, then the content’s meaning is already established. Assigning classes to any of those elements won’t affect that content’s meaning.
This is where we can differentiate content-semantic (e.g.
.submenu) vs visually semantic (e.g.
.btn-success) class naming conventions. Later we’ll also discuss the new kid on the block: functional (or composeable) class naming.
Analyzing Scalable and Performant Methodologies
Many people far smarter than me have written about their experience on scaling CSS. Similarly, many approaches have been born from these conversations. Here are a few and a brief overview of them individually. Hopefully, you’ve already heard of some, and you may be already using a preferred method.
Object Oriented CSS (OOCSS)
Nicole Sullivan first introduced the concept of Object Oriented CSS back in 2009. Her insight and analysis of existing enterprise methods for writing CSS established a larger conversation, which many of the preceding methods stemmed from, and extended on.
The gist of the concept for OOCSS was the idea of marrying traditional object oriented programming methods with CSS. Whereas, objects are merely referring to HTML elements.
The two main tenets of OOCSS are:
Separate structure from skin
Essentially, this means to abstract the structure and positioning styles of an object from the presentational styles, or skin.
Separate container from content
This means to break components’ dependency of their containers. Any object should be able to be placed in another container and still look and behave the same.
Block Element Modifier (BEM)
The Block Element Modifier (BEM) method was developed by Yandex. BEM offers a strict means to class naming in your CSS in order to purpose them as reusable modules.
- Block – Standalone entity that is meaningful on its own. Examples:
- Element – A part of a block that has no standalone meaning and is semantically tied to its block. Examples:
- Modifier – A flag on a block or element. Use them to change appearance or behavior. Examples:
Using a button as an example we might use BEM to write our classes like this:
BEM has a lot more documentation and I encourage you to dig in at GetBem.com.
SMACSS is mostly based on five categories:
- Base rules – Target basic elements only, and does not include classes or IDs. This often can include resets. Examples:
- Layout rules – These are further sub-classified as major and minor layout rules. Major layout styles typically target IDs and can affect things like the
footer. Whereas, minor layout styles (aka Modules) are nested within major layout components, e.g.
nav, or login
- Module rules – A Module is a discreet component. As mentioned above an example is
header. Modules can reside inside of other modules, but should be styled to stand alone. Typically avoid element and ID selectors, and make liberal use of child or descendant selectors where the use may be predictable.
- State rules – Typically used to override or augment a Module or Layout’s rules when differentiating the different states (e.g. active, inactive, expanded, hidden). These are prefixed with
- Theme rules – This is where you can set overrides on any of the above: Base, Layouts, Modules, States. Think of it as setting the chrome on your site, or Modules (aka skinning).
SMACSS is not as opinionated as BEM in its class naming conventions. It has a similar approach to BEM in that it suggests you name your block’s child elements by using the parent block with a hyphen, e.g.
New Generation methodologies
Yes, I’m going to lump the following methodologies into what I’m calling: New Generation methodologies. I tried to cover most of the major milestone methodologies above, but there are many others that helped pave the way for exploration. However, in recent years there seems to have been a bit of underlying commonality between these New Generation methodologies: anti-monolithic, component-based, and single-purpose single property practices. Here are a few:
Atomic CSS (ACSS)
Atomic CSS is developed by Yahoo! Inc. Atomic CSS offers immutable, single property classes to emphasize their singular function. Whereas, monolithic styles often times rely on descendant and contextual selectors. Let’s look at an example of how we might markup Atomic CSS two column layout vs traditional methods.
And here would be a comparison of the CSS used by Atomic CSS vs traditional method.
The traditional example above is where we start to see how these methods can break down in large projects. Should a new requirement be introduced to the two-column component then often times there is more bloat introduced. Whereas, the complexity of rules and selectors become so coupled that it can cause confusion or anxiety on editing existing CSS, and instead, “We create new rules, rather than modify existing ones, because we are not sure the latter is 100% safe.” 
These two libraries are so similar it is hard not to group them. They both use similar feature descriptions, like “composable”, “single purpose” classes. Both are framework agnostic, and ready to plug and play with React, Ember, Angular, Rails, Elm, static HTML, etc.
Tachyons has seemingly become more popular. I speculate that it is because the documentation and resources are robust, and as of this writing the number of Contributors is double that of Basscss on Github. I plan on covering Tachyons in-depth in my next post.
I gave a terse overview of some key methodologies, but each one could easily have a post written on its own. I encourage you to dig deeper into any methods that resonate with you, and your current or next project’s needs.
Stay tuned for the next post in this series: “Evolution of CSS: Overview of Tachyons.”