Are you Single?

I find it interesting when two (or more) people can say something but the way that something is interpreted can be quite different.

Nearly four years ago, Harry Roberts wrote about applying the single responsibility principle to CSS.

Within the article, Harry explains how defining too many properties on a class selector may make it difficult to re-use that class in other contexts, thereby requiring either duplicate CSS properties or overrides to achieve our goals.

He starts with a design of a promotional link like so:

.promo {
    display: block;
    padding: 20px;
    margin-bottom: 20px;
    background-color: #09f;
    color: #fff;
    text-shadow: 0 0 1px rgba(0,0,0,0.25);
    border-radius: 4px;
}

It’s a full-width button, lovingly styled.

However, that single class is doing multiple things at once. But what if you wanted a similar promo link but wanted it inline? How do you solve that problem? Here’s his solution:

.island {
    display: block;
    padding: 20px;
    margin-bottom: 20px;
}

.promo {
    background-color: #09f;
    color: #fff;
    text-shadow: 0 0 1px rgba(0,0,0,0.25);
    border-radius: 4px;
}

Boom! The promo class can be used in both inline and block contexts. The island class creates the block context.

In the HTML, we can now handle the two scenarios we want:

<a href="..." class="island promo">Buy Now!</a>
<h2>You should <span class="promo">Buy Now!</span></h2>

Breaking it down

In this case, the CSS has been broken down into two use cases and we have two CSS classes that serve this purpose. Excellent!

But wait, there’s more. There are a bunch of things that I might want to set consistent margin and padding to including inline-block and flex items. Maybe I should break things down even further?

.block {
    display: block;
}

.spacing {
    padding: 20px;
    margin-bottom: 20px;
}

.promo {
    background-color: #09f;
    color: #fff;
    text-shadow: 0 0 1px rgba(0,0,0,0.25);
    border-radius: 4px;
}
<a href="..." class="block spacing promo">Buy Now!</a>
<h2 class="spacing">You should 
   <span class="promo">Buy Now!</span></h2>

As a project gets more complex, there are going to other ways to break down classes into smaller and smaller components. Which, ultimately, leads you to Atomic CSS, where each class has a very discreet purpose with, usually, just a single property.

<a href="..." class="D(b) P(20px) Mb(20px) Bgc(#09f) C(#fff) Bdrs(4px) Tsh(light)">Buy Now!</a>
<h2 class="P(20px) Mb(20px)">You should 
   <span class="Bgc(#09f) C(#fff) Bdrs(4px) Tsh(light)">Buy Now!</span></h2>

Which one is following the single responsibility theory?

Get Smacked

On the other end of the spectrum, is SMACSS. I advocate creating interface components that are independent of the content it’s trying to style.

Did you notice how there’s something that is made to look like something you can click on (the block link) but the other context was just inline text?

This whole scenario is made up but follow along here. If this were a design I received, I’d be going back to the designer and saying, why is it a link here but not there?

In other words, what’s the purpose of this style? It’s a button. Or a link meant to look like a button. In any case, calling it ‘promo’ is limiting. I’m probably going to want buttons all over the place. Or, if I don’t, at some point, I might. Therefore, I create a button style:

.button {
    padding: 20px;
    background-color: #09f;
    color: #fff;
    text-shadow: 0 0 1px rgba(0,0,0,0.25);
    border-radius: 4px;
}

.button-full {
    display: block;
    margin-bottom: 20px;
}

This is very similar to what Harry had originally written but with different names. Also, I moved the CSS properties around. I want the padding on the button in both contexts but only when it’s full-width do I want it to have the extra margin on the bottom.

The naming convention I used was on purpose. They both start with button. One is the core module name and then the other can be layered on top of it.

Where I apply the single responsibility theory is in saying that an HTML should only have one module applied to it. Island and promo on the same element? Nope. But button and button-full? Climb aboard!

This narrow example gives me pretty much the same results that Harry did but with a bit more consideration added as to why things have been split up the way they have.

It’s one of the reasons that I continue to stick with the categorization that I originally defined in the book, with layouts, modules, states, and themes. There are patterns that reveal themselves in each of these categories.

Which way?

I’m not sure Harry expected to have his example nitpicked and there might’ve been a degree of pointlessness in my doing so. What’s the point of all this then?

There’s no right or wrong here.

Whether you use Harry’s approach, Atomic CSS, or SMACSS, could depend on any number of factors including comfort level and what you’re willing to trade off. Each could be argued as having or not having applied the single responsibility principle to their project.

Knowing which approach you want to take and how to break up your CSS comes from experience. You start to get a feel for where to draw the lines between which properties should go with which classes based on what was painful the last time you built a site.

Published April 05, 2016
Categorized as HTML and CSS
Short URL: https://snook.ca/s/1079

Conversation

4 Comments · RSS feed
Grant Vinson said on April 05, 2016

Definitely more of a SMACCS guy than Atomic. Atomic reminds me of Semantic-UI naming conventions. Name it what it is, and thats it.
So, I might have a stackable grid with the classes "stackable" and "grid". Thats fine and all but I find myself convoluting the classes with more detailed elements. SMACCS solves that problem by keeping everything in order and abstracted. Anyways, just wanted to say how much I love this idea. Trés bon!

Jonathan Snook said on April 05, 2016

Good to hear, Grant!

Cameron Malek said on April 08, 2016

I don't see how the class C(#fff) is different from the HTML attribute color="#FFFFFF" from the days before CSS. To change the color to something else you're editing template files and individual pages rather than a single stylesheet!

I also don't necessarily agree with “HTML should only have one module applied to it.” For example, if the attributes of the .button-full class are a common pattern, that class should be renamed appropriately and be able to be reused on more than just buttons. If you do need to use more linear, intuitive naming schemes for the HTML writers, a Sass mix-in could re-create the module modifiers while keeping the stylesheet DRY; if that pattern changes in a redesign it is modified in only the one spot.

Sean said on April 12, 2016

Having seen Harry Roberts give a talk last year (2015) I heard him mention that we was moving more towards an atomic level (He did not mention atomic). When doing some work for the NHS Harry found it much easier to create smaller modular class names that could be applied as helper classes.

From my point, I still struggle with these principles given a design I will add a structure class and a generic style class and then try to DRY up my code by moving some of the declarations into global classes.

Generally I end up mixing these principles up, I have a text-left/text-right to modify content and over-ride styles but I will still create a component style that aligns the text left without the helper class and content that more or less sticks with the SMACSS categorisation.

As long as once I'm finished the CSS is maintainable and understandable by the next developer then I'm a happy bunny.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.