Naming Convention in CSS
My mind is on CSS quite a bit these days. At Shopify, I'm jumping into projects that already well under way. As a result, it's been a great way to look at what I wrote in SMACSS and see how applicable it is to yet another project. (As if Yahoo! wasn't already enough of a testing ground.)
With Yahoo!, I (and a team of people) were writing the CSS from scratch and creating our mental map of the project as we went along. Jumping into the middle of a project as I am at Shopify, I have to try and figure out why things are done the way they are.
Here's an example of something that I ran into in the CSS:
#loading-header .loading { background: url(spinner.gif) no-repeat 0 0; }
[...separated by a few pages of code...]
#content {
[...separated by more code...]
#loading-header { display:none; }
.row { display:block; }
&.loading {
#loading-header { display:block; }
.row { display:none; }
}
}
The loading class has a spinner. Got it. But wait, there's a loading class inside an element with an ID of loading-header
and another loading class that gets added to the element with an ID of content
. Are they the same somehow? Is there some inheritence that is taking place?
As it turns out, no. These two loading classes were named exactly the same thing but applied in two different contexts. They really had no relation at all except that the #loading-header
(and thus, #loading-header .loading
) is only visible with #content.loading
. (The &.loading
is part of SASS and adds #content
in place of the ampersand.)
One class is a state. Because it's a state, I prefer to prepend all my states with "is-". In this case, it would be "is-loading". The question asked when I first mentioned this is, "isn't the 'is-' redundant?" But as you can see from the example, it isn't. The naming convention clarifies its intent.
In this case, I had to determine intent based on the CSS. Other times, you're looking at the HTML first.
<div id="content" class="loading">
<div id="loading-header">
<div class="loading">
Where do you begin to look in the CSS to find what you're looking for? You'd probably start with a search for ".loading". Now you're left trying to figure out which loading class applies to what element. The swaths of CSS that separated the relevant parts made it harder to see what was going on.
The simple answer to this, of course, is not to naming two different things with the same name. However, I believe a solid naming convention clarifies intent and makes the project easier to understand. We've long applied naming conventions to programmery things like JavaScript and PHP. The same should go for CSS.
Conversation
In this case would it not only be good to change
#content.loading
to#content.is-loading
, but maybe also change#loading-header .loading
to#loading-header .contents
or even#loading-header #loading-contents
if it is unique?I agree. The issue I run into most often is when a project has hit the launch milestone for a time and then a revision will be requested from client that requires additional styles that the developer doesn't or isn't familiar with the entirety of the project so they inject their own 'schema' and then that's perpetuated for each revision. Is there a better way to manage the naming conventions used?
Fullack. Had the same thing in a current project with the same classes nested in each other doing different things. Naming guidelines help internally but not if you have to work with foreign code...
I've started namespacing all my CSS rules with the id of the page they are a part of. So if I have a
#loading-header
on the splash screen, it will be listed as#splash #loading-header
. (Actually, I should probably use a naming convention as you've described to identify what is actually a page.#pg-splash
?)This reduces naming conflicts to the page-level, which is good enough for my needs. (These days most of my web development is for mobile devices, and those designs tend to favour many small pages over few large ones.)
I've been thinking about this for a while now.
This is a good example of a case where some kind of context-driven CSS can be useful. I'd like to write less CSS and avoid using tons of non-semantic classes in the HTML. Naming conventions sound like a good start :)
All my css-classes that have a specific context have the prefix "-".
In my css I never write:
I write:
If everyone writes css this way, we should get no conflict with third part code.
YUI's Widget framework has an interesting take on this. Widget instances have a method
getClassName()
that outputs value for the class attribute based on a configurable prefix, the widget's name and any values to supply to the method:It's not perfect. it's not smart with regards to inheritance, for one thing, but I find that this type of prefixing works really well. Although the class names are long, your selectors are relatively short; poorly-performing selectors like
.container > ul > li > a
are shortened to a snappier.container-list-link
. Also, since it relies on class selectors and not ID selectors, it's incredibly portable.As Phil Karlton said:
This applies to CSS, too.
I think the comments here highlight this, too. Everyone has their own way, that seems right to them - but may conflict with how someone on another team writes their CSS. Seems like this is a dilemma that will continue. Thoughts?
@Richard: yes, changing the naming on the other loading element would be good as well. I would have likely named it ".loading-header" and ".loading-label".
@Brandon: Documentation is best. An organization should have guidelines on how and why things are the way they are. SMACSS also helps.
@Dan M: if all your CSS is namespaced to the page then don't bother putting it in an external CSS file. Keep it on the page. The only benefit of having it in a separate file is that you're pre-caching for pages the user hasn't visited yet. Although, personally, I would try to make things more generic.
@Tobias: that's essentially the problem I describe in this post. The problem is that when I stumble across "-loading", I have to find which parent element it pertains to. And it didn't help that loading-header was inside of content.
@Nate Klaiber: Indeed. Naming things is hard! Much of the SMACSS methodology really comes down to naming things. (Where, how and why are things named the way they are.)
I'm not sure about the best policy for CSS naming conventions. I always seem to find unique situations that either break or force a rethink of my own system on most projects.
I will say that adding comments to the CSS goes a long way to establishing how its being done. As Nate says everyone has their own way. If I can understand what that is by reading a small description and the odd comment in the CSS, its worth its weight in gold.
Unfortunately I have seen this problem too often to believe it's a pure coincidence. BTW is it so good to precede a CSS selector/class with a hyphen?
@Lillan: You can precede a class name with a hyphen, although I'm not personally a big fan of it.
I agree that the Hyphen feels odd.
I generally go by the rule that the name should describe what it does not where it is.
Some of the issues I run into are when working with multiple platforms or frameworks on one project and they all use different naming conventions. In this case, I try to follow that specific platform's convention when I am modifying/adding any CSS for that part of the project.
I've got to say, I never thought of applying a prefix-naming convention before reading your article! And yet.. now I've read it I find myself thinking that that is bloody genius! At the moment like to think that the CSS i write is fairly helpful to any new developers hooking in to a project - I'm a big fan of comments in CSS (and everything else!)
I agree with Moritz as well though - it's all well and good taking on these standards on a personal level, or even a studio level - but unless it's taken on across the board there's always going to be that instant of 'what on earth is going on here' when coming face to face with css that doesn't have these naming conventions.