This isn't quite a post about CSS architecture. This isn't really a post about naming conventions, either. Instead, let's talk about what we're calling elements. The names themselves. The things we use to link blocks of styles to the elements they're associated with.
9 out of 10 developers agree: naming things is by far the most difficult part of writing CSS. This is because we can't predict the future. A class name might make perfect sense one day, then the design changes, and it's a misnomer the next day. We're then tasked with refactoring our markup and styles so that they make sense. Yuck.
How can we remedy this? Pick names that are less likely to change.
We can usually fit a given class name into one of three categories:
- Functional class names
- Content-based class names
- Presentational class names
Class names within a given category tend to share maintainability characteristics. If we make naming decisions with these categories in mind, we can make smarter decisions about what we're calling things–decisions that will make our CSS more resilient to change.
Functional Class Names
<button class="positive-button">Send Message</button>
A functional class name would look something like
selected-tab. The styling of these elements is based on their function or meaning. There is a strong connection between the class name, the styles it applies, and the reason the styles are being applied. That class name is associated with these styles because of this reason.
Because of this solid link between the styles and their element, these styles are unlikely to change. And if you do change what a
positive-button looks like, chances are you'll want to change every instance of a positive button site-wide. If your designer is thinking about changing "a positive button," instead of "the 'Add User' button in the settings menu," you're in a happy, maintainable place. You're thinking in systems, not pages.
Functional class names are great. When possible, this is probably how you want to write styles. But here's the catch: functional class names aren't always possible.
Design isn't always logical. It's easy to give an example for a functional class name when we're talking about buttons. Most of the time, their function is closely related to their styling. But it's not as easy to give examples for the other 99% of styles we write. Sometimes that block needs an inset shadow because it looks nice. Sometimes that icon needs to grow on hover because it's cute. Sometimes that text needs to be orange just because, well, it's orange. Not every visual aspect of a website has a functional justification behind it, and that's okay.
So what's a dev to do? Well, we're at a crossroads. If we can't think of a good functional class name, we can either name that element based on its content, or based on its presentation. Both have different implications for maintainability.
Content-Based Class Names
<button class="submit-button">Send Message</button>
Content-based class names are class names that describe the content they contain. If you've ever seen a class name like
profile-photo, you were looking at a content-based class name.
These class names feel clean. They help keep a clear separation between your content (HTML) and styling (CSS). In theory, this enables you to completely redesign the look and feel of your website without touching your HTML, a la CSS Zen Garden. Seems like a huge perk, right?
Now is when I ask you to sit back and raise the question: "How does this benefit me?"
I've never been asked to redesign a website without touching the HTML. Chances are you haven't either. Sure, some HTML may be locked down as it's integrated with a backend system. But as soon as you lose control over your HTML, chances are you'll need to write some less-than-ideal hacky CSS to make design changes. Keep in mind that CSS Zen Garden is more of a CSS tech demo than an example of maintainable CSS. Don't optimize for a CSS-only redesign if you don't need to.
Content-based class names work fine if you're working on small websites. As your site grows, though, they become less and less appropriate. They're not good for style reuse. What if your
login-button and your
submit-button look the same? How is that represented in your CSS architecture? To keep from repeating a style block you'll either have to comma-separate your selectors, or pull some
extend trickery with the use of a preprocessor. Both of these options are difficult to organize and fit into a large-scale project.
If only there were a better way to reuse blocks of styles...
Presentational Class Names
<button class="green-button">Send Message</button>
Presentational class names describe the way an element looks–like
squiggle-border. The name itself is describing the styles that are being applied.
These classes are conducive to code reuse. They don't care if they're being used to style a product title, a username, or a page heading. They just know they're gonna make text big and bold. This also comes with the benefit of scaling gracefully. As you're developing new components, you're able to grab already-existing styles and slap them onto your new markup. You don't need to worry about where to fit your new styles into a pre-existing architecture since you aren't writing any new styles.
Presentational classes are also very self-describing. A developer inspecting code can infer more about how an element will look if it has the class name
round-image rather than
It could be argued that presentational classes raise some maintainability concerns. Since it blurs the lines between markup and presentation, many design changes will necessitate HTML edits. If you foresee this being a problem for your project, use caution.
... But That's Not Semantic!
Presentational classes have a bad rap. Many people avoid them because they're "not semantic." However, this is a myth, and it was busted by Nicolas Gallagher. It's very important to make the distinction between "semantic HTML" and "semantic classes." Nicolas puts it nicely:
The principle of writing "semantic HTML" is one of the foundations of modern, professional front-end development. Most semantics are related to aspects of the nature of the existing or expected content...
... However, not all semantics need to be content-derived. Class names cannot be "unsemantic". Whatever names are being used: they have meaning, they have purpose. Class name semantics can be different to those of HTML elements.
As I write this, the word "unsemantic" has a red squiggle under it. Unsemantic class names aren't a thing. Every class name has some meaning behind it. As you're writing class names, don't get caught up in creating the most "semantically appropriate" class names. Keep in mind that class names are for developers, not users. Think about creating class names that provide as much information as possible to both your fellow developers and future you.
Functional class names are usually your best bet. When you can use them, do it. If you can't come up with a solid functional name, consider the nature of your project and how it's going to grow. Rule of thumb: content-based class names work better for small sites; presentational class names work better for large sites.
Developers can get touchy about this kind of stuff. Nobody wants a project to become unmaintainable, but everybody has different ideas of how to keep that from happening–particularly so with class names. It's helpful to think about the nature of the type of class names you're using and question how well it lines up with the goals of your project.