You can have multiple classes on an HTML element:
<div class="module p-2"></div>
Nothing incorrect or invalid there at all. It has two classes. In CSS, both of these will apply:
.module { }
.p-2 { }
const div = document.querySelector("div");
console.log(div.classList.contains("module")); // true
console.log(div.classList.contains("p-3")); // false
But what about grouping them? All we have here is a space-separated string. Maybe that’s fine. But maybe we can make things more clear!
Years ago, Harry Roberts talked about grouping them. He wrapped groups of classes in square brackets:
<div class="[ foo foo--bar ] [ baz baz--foo ]">
The example class names above are totally abstract just to demonstrate the grouping. Imagine they are like primary names and variations as one group, then utility classes as another group:
<header class="[ site-header site-header-large ] [ mb-10 p-15 ]">
Those square brackets? Meaningless. Those are there to visually represent the groups to us developers. Technically, they are also classes, so if some sadist wrote .[ {}
, it would do stuff in your CSS. But that’s so unlikely that, hopefully, the clarity from the groups outweighs it and is more helpful.
That example above groups the primary name and a variation in one group and some example utility classes in another group.
I’m not necessarily recommending that approach. They are simply groups of classes that you might have.
Here’s the same style of grouping, with different groups:
<button class="[ link-button ] [ font-base text-xs color-primary ] [ js-trigger ]" type="button" hidden>
That example has a single primary name, utility classes with different naming styles, and a third group for JavaScript specific selectors.
Harry wound up shunning this approach a few years ago, saying that the look of it was just too weird for the variety of people and teams he worked with. It caused enough confusion that the benefits of grouped classes weren’t worth it. He suggested line breaks instead:
<div class="media media--large
testimonial testimonial--main">
That seems similarly clear to me. The line breaks in HTML are totally fine. Plus, the browser will have no trouble with that and JSX is generally written with lots of line breaks in HTML anyway because of how much extra stuff is plopped onto elements in there, like event handlers and props.
Perhaps we combine the ideas of line breaks as separators and identified groups… with emojis!
See the Pen
Grouping Classes by Chris Coyier (@chriscoyier)
on CodePen.
Weird, but fun. Emojis are totally valid there. Like the square brackets, they could also do things if someone wrote a class name for them, but that’s generally unlikely and something for a team to talk about.
Another thing I’ve seen used is data-*
attributes for groups instead of classes, like…
<div
class="primary-name"
data-js="js-hook-1 js-hook-2"
data-utilities="padding-large"
>
You can still select and style based on attributes in both CSS and JavaScript, so it’s functional, though slightly less convenient because of the awkward selectors like [data-js="js-hook-1"]
and lack of convenient APIs like classList
.
How about you? Do you have any other clever ideas for class name groups?
I always thought it’d be cool to use runes for classes in my own work, e.g. ᚸ-button. Then I tried it out in a codepen. It worked, but I could never find any alt codes to easily type runes into the machine. Having really Metal class names fell apart in the face of too much copy-pasting.
One could always create their own Emmet shortcuts for that
Probably easiest way would be binding key combinations for this symbols on the keyboard itself. Through AutoHotkey or similar software.
I never thought about that but I find it a clever idea… :)
The problem with most of these approaches is the potential confusion for other devs especially if you work in large evolving teams. They might scratch their heads and require explanation, or debate the group names and emojis. You may end up not saving any time or cognitive resources in the end!
I think the simplest way to visually separate without too much confusion is by double-spacing the groups. Though even then you may get a comment about removing extra whitespace!
Since reading a friends post back in 2013 – https://beneverard.co.uk/blog/using-slashes-within-the-html-class-attribute/ – I’ve been using the pipe
|
to separate the different groups of classnames used with my HTML.It’s still working for me and the several teams I’ve worked with.
It’s a nice visual key to ‘these classnames are for this and these classnames are for this”
Actually I use a double space to separate visually groups of classes. It’s subtle but it’s a little better than nothing and very easy to apply.
Plus if you prefix your classes (like
u-xxx
for a utility class for example), you can lint that.Vertical bars:
<div class="stuff | other stuff | more stuff">
Square brackets is an interesting idea, but for me, I think it’s enough with just name spacing the classes. I usually have a list of name spaces like u- for utility, c- for component, l- for layout, js- for javascript etc.
I’ve used data attributes for content variation in the past. It’s one of those things you could do with classes, but I find it helps to clarify things. An example is a block of content with links in it. The links don’t have any classes for styling, but rather are styled in context ( .something > a {} ). Each link has a data-target attribute that contains the name of the website it directs to. The benefit of this is that I can target links individually for styling (maybe a Facebook link turns blue and an Instagram link turns pink) but I can also use the data-attribute value in a pseudo element, such as if the link text isn’t the name of the destination and I want to show a styled overlay on hover. Using this method allows me to try out different styles, or even switch between them according to themes, without changing the markup at all.
I had never really considered organizing classes in a fashion that incorporated some sort of container to group related items. In my mind BEM sort of does this already… provided that you’re declaring them in order (ie.
block block__elem block--mod
)That being said I kind of like the idea of the brackets… but I’d probably just with a vertical line (ie.
container-fluid | bg-primary text-secondary | p-2 m-4
)To me that’s a little cleaner than brackets… or at least involves less typing.
If you order your classes alphabetically, you can avoid this entire issue.
$(element).addClass(‘foo’);
This is what makes me think this “grouping system” is useless. JavaScript libraries and frameworks aren’t designed to manipulate classes while maintaining the grouping sense. The possible solution lies in some webpack module (that I don’t know yet) maybe (?).
The grouping is for developers only. For taking a peak at some markup and seeing what’s going on. It doesn’t matter what’s going on in the DOM.
Any idea how this effects specificity?
Slightly related to this topic – I’m a big fan of prepending any classes used in JS with js-. So you usually end up with something like:
This allows any developer familiar with the project or not to instantly know whether the class is being used in CSS or Javascript. No more bugs where you remove an innocent looking class to later find out some Javascript depended on that class.
Purely for styling I use BEM, whilst it doesn’t technically group selectors it really helps.