Lesson 3: Naming
Naming things is hard, so hard in fact that you’d be hard-pressed to avoid the following quote (it’s become a bit of a meme):
>There are only two hard things in Computer Science: cache invalidation and naming things — Phil Karlton
When we talk about “names” in CSS, often what we’re really taking about are the different attributes we give to HTML elements to identify them. Things like class names, IDs and name attributes which can be referenced by selectors.
In this lesson we’re going to cover:
- Semantic naming: what it is and why it’s useful
- How to minimise “name collisions”
- How name length should reflect reusability
- How to effectively “namespace” in CSS
Semantic naming #
Semantic naming is a commonly practiced philosophy in CSS, it’s main tenet is:
Explain what an element is, not what it looks like
Imagine describing an element on a page to someone who isn’t able to see it. Instead of relying on it’s visual characteristics (“it’s the big red button”), you’d have to consider some of the following:
- What is it? Is it a link? Is it a button? Is it an image?
- What is it’s purpose? Is it responsible for linking to a specific page? Does it show particular kind of image?
- What context differentiates it? If the element is surrounded by similar elements, how do you avoid ambiguously naming it?
When is semantic naming useful? #
Let’s consider an example. We have a bunch of text and want to make specific words bold.
Seems sensible enough so far. A few weeks later, we decide that instead of making these words bold, we want to make them pink!
But we’ve forgotten to update the class name to reflect the changes to the CSS, so now there’s a confusing semantic mismatch. We’ve got a class that says that the text is bold, but in reality it’s pink and not bold! Anyone new coming to this HTML is going to have a puzzling job of figuring out what’s going on.
To rectify this situation, we need to update all the class names to something that accurately reflects the current nature of the pink elements. We could rename the class to .pink-text
, but this just leaves us in the same situation as before! If we decide pink isn’t the colour for us, then we’ve got to go and rename all the classes again.
In this toy example, it’s not a big deal and would only take us a few seconds, but in a large codebase these classes could live in Javascript, HTML and/or CSS in all sorts of interpolated and concatenated formats. Finding every occurrence can be quite tricky and has a high chance of silently breaking some part of the visual design if you miss anything.
So what’s the solution? Semantic naming!
But before we arrive at the fix, we have to properly understand the problem. The core issue is that we’ve named the class by it’s visual properties which, in an evolving front-end, will often change. To find a solution, first we have to figure out why we are making this text bold or pink. What’s the intention? What’s the point?
In this scenario, what we really want to do is highlight or emphasise these specific words to the reader. We want to visually accentuate that these words are important.
So now we understand the problem, what do we name the class? Well just by stating our intention we’ve armed ourselves with the vocabulary! Highlight, emphasis, accentuation. Any of these would work a treat, and the best thing about them is that they accurately describe the elements without coupling themselves to specific visual design decisions.
So to summarise:
Avoid coupling names to CSS rules
Train your nose to these kinds of code smells, .red-button
, .margin-bottom-20px
, .left-aligned-text
. 💩🤢
Semantic names are more maintainable #
As the above example illustrates, semantic naming is more resilient to design changes; classes are more likely to be relevant to the elements they’re applied to and less likely to become out-of-date.
It also has the advantage of documenting your elements. If you’re annotating, via class names, what each bit of HTML is instead of how it looks, then someone unfamiliar with a bit of UI can see how the HTML and CSS join up to the visual elements.
That means better knowledge-sharing and less mental load when working with semantically-named elements, producing a more maintainable codebase overall.
Try to avoid name collisions #
In CSS, name collisions commonly refer to when you accidentally give an element a name that is already used by an unrelated, existing element. When this happens, the styles you give your new element will start to interfere with the existing elements.
These issues are sneaky and hard to spot, as the elements you’re impacting may be in a totally different section of your site. You may not think to check the contact page if you’re editing the home page! This override behaviour is core to CSS’s cascade, but unfortunately assumes authors are omniscient and don’t make mistakes!
Let’s dig further into some solutions to tackle name collisions.
Shorter names = more reusable #
To avoid name collisions, try adopting the following naming convention:
Keep an element’s name length inversely proportional to it’s reusability
In other words, use shorter names for generic, reusable elements and longer names for uncommon elements, that are used maybe once or twice.
When we look at linguistics and how we communicate with each other, the same rule applies. Shorter terms (e.g. “cat”) tend to be more generic than longer ones (e.g. “spooky black cat”) and so our CSS naming should follow this same pattern.
But simply adopting this convention won’t magically avoid name collisions. Instead, it provides a system for predicting the likelihood of a name collision occurring when a new element is introduced.
If a name is long and composed of several words, or you’re working on a small CSS codebase, you can feel confident that a name collision is unlikely (though not impossible!). In contrast, alarm bells should be going off when you introduce an element with a short name (e.g. .title
, .button
) to a large, existing codebase.
In those situations, you should:
- First ask yourself whether the name should be longer and more specific to reflect it’s intended level of reusability.
- Then check for any existing selectors that already use the name and pose a collision risk.
If any selectors are found, you could either refactor the existing selectors, or change the name you’re introducing to bypass the collision. The latter is usually much easier, and less likely to cause visual regressions, but occasionally the existing styles may be out of date or poorly named, thus making a refactor worth the effort.
Namespacing #
Many programming languages today have a concept of “namespacing”. A namespace is a generic term for a named set of things, were these things are often classes, functions or variables. Things in the same namespace can’t have the same name, but things in different namespaces can. It’s a handy way of sensibly grouping related things together, but also provides a tool to avoid name collisions.
A common way of referencing namespaced things is done by adding their namespace as a prefix to their name:
Foo.Object
Bar.Object
In the above example, Foo
and Bar
are two different namespaces, that each contain their own Object
. Despite both being named Object
, both Foo.Object
and Bar.Object
would be considered separate, independent, and unrelated because they sit in different namespaces.
So how does this relate to CSS? Namespaces aren’t an explicit feature in CSS, but there are a few methods of namespacing styles.
Namespacing by parent #
One common method of namespacing CSS styles is by including the parent element in selectors, for example:
.home .primary-button {
background-color: red;
}
.about-us .primary-button {
background-color: green;
}
By doing so, the .primary-button
styles are grouped depending on which parent element they’re nested in; in this scenario, the parent elements .home
and .about-us
could be considered the namespaces. However, due to CSS’s cascade, it’s not actually as clear cut as cut as that. If we introduced this style into the mix…
.primary-button {
color: magenta;
}
…we would notice that it also affects .primary-button
elements nested inside .home
and .about-us
parents. This contravenes the whole idea of elements of different namespaces being independent of one another, therefore isn’t a great way of namespacing in CSS. ❌
Namespacing by name prefix #
Another alternative method to CSS namespacing is to add a prefix to your element names which indicates the namespace it belongs to. Returning to the above .primary-button
example, if we use a suffix namespace, it could look something like this:
.home-primary-button {
background-color: red;
}
.about-us-primary-button {
background-color: green;
}
Looking at these styles, we can see they’re both “primary buttons”, but they belong to different pages, or namespaces.
If we were to again introduce a .primary-button
class, the CSS cascade wouldn’t interfere with the above styles since they don’t share the same class name, making this method a much more reliable way of namespacing styles. 🙌
One thing to be aware of with this method, is that it’s important to be able to distinguish the namespace prefix from the element name. With the above .home-primary-button
class, is the namespace home-primary
or is just home
? It introduces ambiguity that can make it a little harder to understand what a class is describing, and also where in the codebase it might live. Here’s some possible solutions to this problem:
- Use a different separator between your namespace and name to the one used to separate the words of a term, e.g.
.home_primary-button { ... }
- Get rid of separators between words of a term and only use them to distinguish namespace from name, e.g.
.home-primaryButton { ... }
Either solution would do a good job of reducing name collisions, but have the slight inconvenience of increasing the name length of all your CSS names. Due to the pernicious risks of name collisions, where styles unrelated to your change can be broken without your knowledge, a few extra character strokes is a small cost to pay to bypass the problem.
End of Lesson 3 #
Naming is hard, and more often than not it’s more art than science.
Even when you do find the “perfect” name, the battle has just begun. Making sure the name continues to reflect it’s element in the future requires thought, as does avoiding conflicts with similar elements.
Equipped with the above guidelines, you should now have a few pointers ready for when the time comes to name your next widget. Try to understand what it is and how it should exist among existing elements, and the name should become much more apparent.
Lessons
- Lesson 1: Specificity
- Lesson 2: Scope
- Lesson 3: Naming ← You're here
- Lesson 4: Variations
- Lesson: BEM Coming Soon
- Lesson: SCSS Coming Soon
-
Lesson:
position
Deep Dive Coming Soon - Lesson: Reusability Coming Soon
- Lesson: Units Coming Soon
- Lesson: Media Queries Coming Soon
-
Lesson:
display
Deep Dive Coming Soon - Lesson: Flexbox Coming Soon
- Lesson: Grid Coming Soon
- Lesson: Inheritance Coming Soon
- Lesson: Layout vs Aesthetics Coming Soon
- Lesson: Fixing Bad CSS Coming Soon
- Lesson: Composability Coming Soon
- Lesson: File Organisation Coming Soon
- Lesson: Accessibility Coming Soon