Better CSS

Lesson 3: Naming

Nam­ing things is hard, so hard in fact that you’d be hard-pressed to avoid the fol­low­ing quote (it’s become a bit of a meme):

>There are only two hard things in Com­puter Sci­ence: cache inval­id­a­tion and nam­ing things — Phil Karlton

When we talk about names” in CSS, often what we’re really tak­ing about are the dif­fer­ent attrib­utes we give to HTML ele­ments to identi­fy them. Things like class names, IDs and name attrib­utes which can be ref­er­enced by select­ors.

In this les­son we’re going to cover:

Semant­ic nam­ing #

Semant­ic nam­ing is a com­monly prac­ticed philo­sophy in CSS, it’s main ten­et is:

Explain what an ele­ment is, not what it looks like

Ima­gine describ­ing an ele­ment on a page to someone who isn’t able to see it. Instead of rely­ing on it’s visu­al char­ac­ter­ist­ics (“it’s the big red but­ton”), you’d have to con­sider some of the following:

When is semant­ic nam­ing use­ful? #

Let’s con­sider an example. We have a bunch of text and want to make spe­cif­ic words bold.

See the Pen  NWGjKEg by Joe For­shaw (@joeforshaw) on Code­Pen.

Seems sens­ible enough so far. A few weeks later, we decide that instead of mak­ing these words bold, we want to make them pink!

See the Pen  ZEbKEQV by Joe For­shaw (@joeforshaw) on Code­Pen.

But we’ve for­got­ten to update the class name to reflect the changes to the CSS, so now there’s a con­fus­ing semant­ic mis­match. We’ve got a class that says that the text is bold, but in real­ity it’s pink and not bold! Any­one new com­ing to this HTML is going to have a puzz­ling job of fig­ur­ing out what’s going on.

To rec­ti­fy this situ­ation, we need to update all the class names to some­thing that accur­ately reflects the cur­rent nature of the pink ele­ments. We could rename the class to .pink-text, but this just leaves us in the same situ­ation as before! If we decide pink isn’t the col­our 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 code­base these classes could live in Javas­cript, HTML and/​or CSS in all sorts of inter­pol­ated and con­cat­en­ated formats. Find­ing every occur­rence can be quite tricky and has a high chance of silently break­ing some part of the visu­al design if you miss anything.

So what’s the solu­tion? Semant­ic naming!

But before we arrive at the fix, we have to prop­erly under­stand the prob­lem. The core issue is that we’ve named the class by it’s visu­al prop­er­ties which, in an evolving front-end, will often change. To find a solu­tion, first we have to fig­ure out why we are mak­ing this text bold or pink. What’s the inten­tion? What’s the point?

In this scen­ario, what we really want to do is high­light or emphas­ise these spe­cif­ic words to the read­er. We want to visu­ally accen­tu­ate that these words are important.

So now we under­stand the prob­lem, what do we name the class? Well just by stat­ing our inten­tion we’ve armed ourselves with the vocab­u­lary! High­light, emphas­is, accen­tu­ation. Any of these would work a treat, and the best thing about them is that they accur­ately describe the ele­ments without coup­ling them­selves to spe­cif­ic visu­al design decisions.

So to summarise:

Avoid coup­ling names to CSS rules

Train your nose to these kinds of code smells, .red-button, .margin-bottom-20px, .left-aligned-text. 💩🤢

Semant­ic names are more main­tain­able #

As the above example illus­trates, semant­ic nam­ing is more resi­li­ent to design changes; classes are more likely to be rel­ev­ant to the ele­ments they’re applied to and less likely to become out-of-date.

It also has the advant­age of doc­u­ment­ing your ele­ments. If you’re annot­at­ing, via class names, what each bit of HTML is instead of how it looks, then someone unfa­mil­i­ar with a bit of UI can see how the HTML and CSS join up to the visu­al elements.

That means bet­ter know­ledge-shar­ing and less men­tal load when work­ing with semantic­ally-named ele­ments, pro­du­cing a more main­tain­able code­base overall.

Try to avoid name col­li­sions #

In CSS, name col­li­sions com­monly refer to when you acci­dent­ally give an ele­ment a name that is already used by an unre­lated, exist­ing ele­ment. When this hap­pens, the styles you give your new ele­ment will start to inter­fere with the exist­ing elements.

These issues are sneaky and hard to spot, as the ele­ments you’re impact­ing may be in a totally dif­fer­ent sec­tion of your site. You may not think to check the con­tact page if you’re edit­ing the home page! This over­ride beha­viour is core to CSS’s cas­cade, but unfor­tu­nately assumes authors are omni­scient and don’t make mistakes!

Let’s dig fur­ther into some solu­tions to tackle name collisions.

Short­er names = more reusable #

To avoid name col­li­sions, try adopt­ing the fol­low­ing nam­ing convention:

Keep an element’s name length inversely pro­por­tion­al to it’s reusability 

In oth­er words, use short­er names for gen­er­ic, reusable ele­ments and longer names for uncom­mon ele­ments, that are used maybe once or twice.

When we look at lin­guist­ics and how we com­mu­nic­ate with each oth­er, the same rule applies. Short­er terms (e.g. cat”) tend to be more gen­er­ic than longer ones (e.g. spooky black cat”) and so our CSS nam­ing should fol­low this same pattern.

But simply adopt­ing this con­ven­tion won’t magic­ally avoid name col­li­sions. Instead, it provides a sys­tem for pre­dict­ing the like­li­hood of a name col­li­sion occur­ring when a new ele­ment is introduced.

If a name is long and com­posed of sev­er­al words, or you’re work­ing on a small CSS code­base, you can feel con­fid­ent that a name col­li­sion is unlikely (though not impossible!). In con­trast, alarm bells should be going off when you intro­duce an ele­ment with a short name (e.g. .title, .button) to a large, exist­ing codebase.

In those situ­ations, you should:

  1. First ask your­self wheth­er the name should be longer and more spe­cif­ic to reflect it’s inten­ded level of reusability.
  2. Then check for any exist­ing select­ors that already use the name and pose a col­li­sion risk.

If any select­ors are found, you could either refact­or the exist­ing select­ors, or change the name you’re intro­du­cing to bypass the col­li­sion. The lat­ter is usu­ally much easi­er, and less likely to cause visu­al regres­sions, but occa­sion­ally the exist­ing styles may be out of date or poorly named, thus mak­ing a refact­or worth the effort.

Namespa­cing #

Many pro­gram­ming lan­guages today have a concept of namespa­cing”. A namespace is a gen­er­ic term for a named set of things, were these things are often classes, func­tions or vari­ables. Things in the same namespace can’t have the same name, but things in dif­fer­ent namespaces can. It’s a handy way of sens­ibly group­ing related things togeth­er, but also provides a tool to avoid name collisions.

A com­mon way of ref­er­en­cing namespaced things is done by adding their namespace as a pre­fix to their name:

Foo.Object
Bar.Object

In the above example, Foo and Bar are two dif­fer­ent namespaces, that each con­tain their own Object. Des­pite both being named Object, both Foo.Object and Bar.Object would be con­sidered sep­ar­ate, inde­pend­ent, and unre­lated because they sit in dif­fer­ent namespaces.

So how does this relate to CSS? Namespaces aren’t an expli­cit fea­ture in CSS, but there are a few meth­ods of namespa­cing styles.

Namespa­cing by par­ent #

One com­mon meth­od of namespa­cing CSS styles is by includ­ing the par­ent ele­ment in select­ors, for example:

.home .primary-button {
  background-color: red;
}

.about-us .primary-button {
  background-color: green;
}

By doing so, the .primary-button styles are grouped depend­ing on which par­ent ele­ment they’re nes­ted in; in this scen­ario, the par­ent ele­ments .home and .about-us could be con­sidered the namespaces. How­ever, due to CSS’s cas­cade, it’s not actu­ally as clear cut as cut as that. If we intro­duced this style into the mix…

.primary-button {
  color: magenta;
}

…we would notice that it also affects .primary-button ele­ments nes­ted inside .home and .about-us par­ents. This con­tra­venes the whole idea of ele­ments of dif­fer­ent namespaces being inde­pend­ent of one anoth­er, there­fore isn’t a great way of namespa­cing in CSS. ❌

Namespa­cing by name pre­fix #

Anoth­er altern­at­ive meth­od to CSS namespa­cing is to add a pre­fix to your ele­ment names which indic­ates the namespace it belongs to. Return­ing to the above .primary-button example, if we use a suf­fix namespace, it could look some­thing like this:

.home-primary-button {
  background-color: red;
}

.about-us-primary-button {
  background-color: green;
}

Look­ing at these styles, we can see they’re both primary but­tons”, but they belong to dif­fer­ent pages, or namespaces.

If we were to again intro­duce a .primary-button class, the CSS cas­cade wouldn’t inter­fere with the above styles since they don’t share the same class name, mak­ing this meth­od a much more reli­able way of namespa­cing styles. 🙌

One thing to be aware of with this meth­od, is that it’s import­ant to be able to dis­tin­guish the namespace pre­fix from the ele­ment name. With the above .home-primary-button class, is the namespace home-primary or is just home? It intro­duces ambi­gu­ity that can make it a little harder to under­stand what a class is describ­ing, and also where in the code­base it might live. Here’s some pos­sible solu­tions to this problem:

  1. Use a dif­fer­ent sep­ar­at­or between your namespace and name to the one used to sep­ar­ate the words of a term, e.g.
    .home_primary-button { ... }
    
  2. Get rid of sep­ar­at­ors between words of a term and only use them to dis­tin­guish namespace from name, e.g.
    .home-primaryButton { ... }
    

Either solu­tion would do a good job of redu­cing name col­li­sions, but have the slight incon­veni­ence of increas­ing the name length of all your CSS names. Due to the per­ni­cious risks of name col­li­sions, where styles unre­lated to your change can be broken without your know­ledge, a few extra char­ac­ter strokes is a small cost to pay to bypass the problem.

End of Les­son 3 #

Nam­ing is hard, and more often than not it’s more art than science.

Even when you do find the per­fect” name, the battle has just begun. Mak­ing sure the name con­tin­ues to reflect it’s ele­ment in the future requires thought, as does avoid­ing con­flicts with sim­il­ar elements.

Equipped with the above guidelines, you should now have a few point­ers ready for when the time comes to name your next wid­get. Try to under­stand what it is and how it should exist among exist­ing ele­ments, and the name should become much more apparent.

Lessons