2012.09.10

SOLID CSS

CSS was meant to style academic documents and simple sites (eg. wiki, blogs) where the cascade and descendant selectors makes a lot of sense. Unfortunately many sites we build nowadays are way more complex than that, and what used to work on simple projects doesn’t scale very well. We need to find smarter ways to code CSS to avoid the common issues and re-think the way we do our work. We should learn from the experience of other devs working in different domains, and apply into our own domain. Things like separation of concerns, modularity, encapsulation, DRY can (and should) be applied to large scale CSS projects as well. The main problem is that most people who are good at CSS doesn’t necessarily have a Computer Science background, most of them started as designers and learned CSS by themselves (that was my case…). That’s the main reason why I’m writing this post.

I won’t get into too much details/examples but will try to explain briefly each concept. Some of the SOLID principles are open to multiple interpretations on the CSS context - since we are shoehorning the concepts - that’s one of the reasons why I decided to not give detailed examples. I also think we should understand the idea and not be tied to a specific implementation.

What is a large CSS project?

The notion of a large project varies a lot, I used to think that a project with 2000+ lines of CSS was big but nowadays most of my projects have more than 4000 lines of CSS and I don’t think they are that big. Organization and the structure of the project can make a huge difference in the “perceived size” of an application. But for the sake of brevity let’s just consider that anything that requires more than 4K lines of well-written CSS is a non-trivial application/site. When a project is under 1-2K LOC it doesn’t really matter how chaotic things are, you can still wrap your head around it. Beware that big messes usually starts small and that it’s easier to start with a good structure than to change it later.

The benefits of the techniques below will only be perceived after your app reaches a certain size and will increase exponentially as the project grows. The benefits will also vary a lot based on the kind of project, be pragmatic about it, try to understand the reasoning behind it and think if it does apply to your project. - I don’t follow these rules on all projects and you certainly shouldn’t as well.

SOLID

SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time. The term was coined by Uncle Bob and I’m pretty sure he didn’t had CSS in mind (although I didn’t asked him).

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Single Responsibility Principle

This principle states that an object should have only a single responsibility, and that responsibility should be entirely encapsulated by the object. When applied to CSS this means that we should separate structure from presentation, instead of creating a single class and/or element that does both, we should decouple them so you can change the skinning of the components without affecting the structure.

One way of doing that is to delegate the dimensions of the element to a grid system (adding multiple classes to the element or extending a base class if using a preprocessor) or set the size on a parent element.

CSS rules should have a high cohesion, you shouldn’t normally see too many different kinds of rules grouped together. You shouldn’t have text styles + borders + colors grouped with dimensions + positioning and floats.

By doing so we can reuse the same modules inside a different container and increase the chance of reuse. It will also make maintenance easier since you can change the skinning without affecting the structure and can toggle the visual easily based on the context (eg. element with same structure but different colors).

Another good tip is to break your code into multiple files - each file is responsible for a single responsibility - that way it’s easier to work on a team (less conflicts) and your CSS will also be easier to understand since everything is grouped by context.

Open/Closed Principle

“software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”

That means that you should make it easy to overwrite/extend the base rules and should avoid editing the base classes.

You should only edit a base class if you are fixing an error, never add new behavior, otherwise you might introduce conflicts. That means that you should not change your reset.css file or edit rules that affects multiple elements after the project is stable. Create a new class that augments it instead of editing it.

In many projects I avoid setting base styles to tags as much as possible, specially when the design doesn’t follow a clear semantic structure – when for instance we might need 20+ font styles and the same elements might have different spacing/color/weight depending on the context. If you reduce the amount of rules that affects global elements you will also reduce the chance of breaking the open/closed principle.

Another main advantage of not having base styles is that you won’t need to overwrite the defaults as much. (but you might need to set more styles).

Liskov Substitution Principle

“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”

Classes that @extend others shouldn’t have a different behavior than the base class. You should be able to toggle between them without affecting the correctness of the app.

The idea behind this principle is that if you can swap Parent classes with their Children, without causing any undesired side effects, you will have a system that is more flexible and easier to understand. It will increase code reuse on cases that you couldn’t predict when the project started.

That means, modifiers should ideally affect only things that wouldn’t break the layout. If the base class doesn’t have a fixed height the child class shouldn’t have as well, the display and position also shouldn’t be changed.

Remember that composition is usually preferred over inheritance.

PS: I don’t follow this principle by heart on my CSS, specially since I use modifiers more as a Decorator than a subclass. But if you are using a preprocessor on a large project and (ab)using the @extend feature that is something you should care about.

Interface Segregation Principle

“many client specific interfaces are better than one general purpose interface.”

That means, it’s better to have multiple specific base modules than to have a single generic one. It will increase the cohesion of your modules and make code easier to refactor/change/maintain (since it reduces tight coupling).

Sometimes it can be really tempting to create a base module that fits multiple scenarios trying to increase code reuse as much as possible. To be honest, lately I’ve been thinking that not all code reuse is a good thing. If you are doing it just for the sake of reusing (specially CSS) you might be increasing the coupling between modules without a need, that will make further changes harder to implement since it will cause a ripple effect to undesired modules (eg. changing the margin around an article in the homepage would also affect the margin around a blog post on the inner pages).

This problem might be hard to spot and even hard to replicate unless the project requirements change (and they usually do change). If you find yourself redefining many properties every time you need to augment a certain class, your base styles are probably too generic.

Dependency Inversion Principle

  1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
  2. Abstractions should not depend upon details. Details should depend upon abstractions.

I like to think this rule on the CSS domain means that the container shouldn’t care about the existence and the visual style of its children as long as it behaves how it expects it to behave. For an .article component it shouldn’t matter how the .title is styled, as long as the title doesn’t break the layout. We should delegate the styling of child components to their own modules and do it in a way that the child elements can be swapped without affecting the parent element. This is the core idea behind OOCSS.

Nested selectors are a sign that you might be breaking this rule. Instead of making nested selectors like #sidebar .group > h3 you should create a new class .group-title. That way it can be an <h3>, <div> or any other element you need. It will be easier to create new modules with slightly different styling/behavior by simply swapping the dependencies (child elements). This also favors composition over inheritance.

Conclusion

Most concepts can be applied into multiple domains, understand the problems they try to solve so you can apply them when appropriate.

“Smart people learn from their mistakes. But the real sharp ones learn from the mistakes of others.” – Brandon Mull

Keep your code organized and you won’t lose momentum. You shouldn’t be afraid of making changes to your CSS, if your modules are loosely coupled they won’t interfere with each other, which means they will be easier to maintain.

Recommended Read

If you want to see some code samples and how to apply these concepts check the links below, they get into further details about the problems and solutions.

Translations

This article is also available in Japanese.


Comments

Great article.

Twitter Bootstrap follow these principles and works really well.

As a designer that started learning CSS five years ago, before really learning HTML (yikes!), and am now learning programming, I found this article not only interesting, but somewhat validating. I have thought, independently, about some of these principles, though I don't always follow through. And the other principles are quite enlightening.

Great Article, after reading it, i already know that I have to fix some css files in my project!

Really good read. I think people often see CSS as a simple declarative language that doesn't require this level of thought (it is, but it does). Whether you're working on a small brochure site or a massive application, approaching CSS like a more formal programming language is a wise thing to do and will help your sanity if you ever come back and have to read/maintain/alter your code in the future.

“many client specific interfaces are better than one general purpose interface.” Totally agree. The staff from Twitter should know that.

I've been working on a huge web app for the past six months and almost all of the refactoring (read: learning) I've been doing since I started has evolved into the very same principals you're talking about here. This is the blog post I wish I wrote, I couldn't agree more with it!

Nice article.

But I'm not convinced on this point: "CSS rules should have a high cohesion, you shouldn’t normally see too many different kinds of rules grouped together. You shouldn’t have text styles + borders + colors grouped with dimensions + positioning and floats."

I combine text styles and box styles, and sometimes even positioning, frequently. Like for creating hand-built buttons ("a.button"), and bars, and <code> blocks, and image captions. I'm not sure how I would separate out those concerns.

Hi Miller,

Nice article.

I'm writing a CSS Framework with a closed philosophy to your article. I would like to invite you to read it and you will be wellcome to participate.

https://github.com/gc-victor/tortillacss

Nice Article! i'd like to see some examples for every point you explained.

@Justin you would separate the concerns by splitting the rules into individual classes and mixin them to achieve the desired display. You create a base class that sets the structure and then add other classes to set the visual style, a good example of it is the media object. @csswizardry article about Single Responsibility gets into more details as well.

@Alex the links at the bottom of the article contain examples of these practices. I didn't added my own examples since I think it would shift the focus to the examples instead of thinking about the concepts behind it.

Cheers

Fantastic article, thanks! It's nice to have all the theory and some really good examples all in one place, and I like the real-world, down-to-earth writing style — makes it a really enjoyable read.

I try to follow 'best practices' like these but it doesn't always work out that way. I have a feeling I'm not the only one though :)

Sitting back from the computer and refining our development practise is definitely a hot topic at the moment. I'm starting to think being a good programmer is important. Not just because of all the useful command line tools available now but because good programmers can process large amounts of data into a coherent and (hopefully elegant) documents.

On that note, here's how I structure rather huge CSS projects https://twitter.com/i_like_robots/media/slideshow?url=pic.twitter.com%2F2Mh6NQS6

This is a great article, the methods suggested in here reminded me of what i see when i look at the stylesheets from jquery ui. Definitely something I intend to practice in my web development from now on. Thanks for the lesson.

[...] SOLID CSS- SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time. [...]

[...] to what makes sustainable CSS: however, one of the best articles that I have read on the subject is this post on SOLID principles by Miller Medeiros. SOLID is an acronym for five basic principles of object-oriented programming and design that when [...]

SOLID CSS. Yes! Well written, digested, and applied. I agree with the majority of SOLID as applied to CSS. There are certain instances where it doesn't quite fit as well, but they are still important concepts to understand.

Open/Closed Principle is probably the most applicable to modular/OO CSS. This principle alone can save you loads of grief when authoring modules. I commend Harry Roberts for being the first to spot this programming gem and write about it on his site [csswizardry.com]

Modular/OO CSS is the way to go these days on sites large and small. Kudos to you, Miller, for this write-up on SOLID and CSS!

Cheers!

[...] SOLID CSS- SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time. [...]

[...] SOLID – Applying the 5 basic principles of object-oriented programming and design to CSS for large-scale projects. Study this. [...]

[...] SOLID CSS- SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time. [...]

[...] SOLID CSS- SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time. [...]

I recommend that everybody take a look at BEM Methodology invented in Yandex.

[...] As a reminder here’s a brief definition of all five SOLID principles. [...]

Good day! I know this is kind of off topic but I was wondering which blog platform are you using for this site? I'm getting tired of Wordpress because I've had problems with hackers and I'm looking at options for another platform. I would be great if you could point me in the direction of a good platform.

I was recommended this blog through my cousin. I'm no longer positive whether or not this publish is written through him as no one else realize such specified approximately my difficulty. You're amazing! Thanks!

[…] Apply some classic programming principles to make your css SOLID […]

Leave a Comment

Please post only comments that will add value to the content of this page. Please read the about page to understand the objective of this blog and the way I think about it. Thanks.

Comments are parsed as Markdown and you can use basic HTML tags (a, blockquote, cite, code, del, em, strong) but some code may be striped if not escaped (specially PHP and HTML tags that aren't on the list). Line and paragraph breaks automatic. Code blocks should be indented with 4 spaces.