When developing software, it's generally desirable to hide the details. This allows you to increase the cohesion of parts in our software, and to decouple them from each other via well-defined interfaces or boundaries.
This is a common approach when it comes to isolating ourselves from external dependencies in our code. But why only apply it to code we write for the back-end? The same abstraction principles apply no matter what external dependency we want to isolate ourselves from.
Thus, it can and should be applied to any CSS framework we use. Regardless of whether we're using Bootstrap, Pure, Less, Blueprint, 960, or any other framework, our applications should not have any direct coupling to an external framework. We should not use any CSS classes that were not defined by us for our project.
I will use Yahoo!'s Pure framework for the following code examples, but the principles apply for any framework.
pure-g classes to create a grid, and several
pure-u-* classes as units/columns within these grids.
A grid with two buttons next to each other can be defined like this:
As we can see, this markup contains many references to classes that are defined by Pure. By doing that, we have coupled the view directly to the framework we've chosen.
Directly coupling to a framework is not always a good approach. Developers react with hesitation as soon as they introduce such a tight coupling in a language like Ruby, and the same abstraction and isolation principles should apply to CSS as well. The view belongs to our application, and therefore we should isolate any external dependency from that.
Ideally, we would write the previous code in a way that puts us in charge of what CSS classes the elements use.
An example of that would look something like this:
The classes in this example do a better job of expressing what the HTML intends to do.
grid-container instead of
pure-g, because that's what
pure-g really was.
half-width instead of
pure-u-1-2 was really just a
div that spanned half of the width of its parent element.
And we use
button instead of
pure-button, because... well, it's just a button.
How can we achieve CSS isolation?
To be able to use the CSS classes in the second example, I used Sass. Sass allows you to “extend” new selectors from existing selectors.
With this feature, we can create new selectors for our views that match the domain of the application we're developing.
The definitions for the classes of the last example look like this:
Sass will create the classes with the appropriate content for us. With these definitions,
.grid-container will have the same declarations that
This is not only possible for single classes, either. Multiple usages of classes can also be merged together.
For example, a button that is coloured in Pure's primary colour is declared like this:
Its SCSS declaration looks like this:
We are now able to declare the button with better expressed intent:
What does this tell us?
By isolating from the CSS framework, we no longer couple our views to any specific framework.
When we want to switch to another framework, we do not have to update all the views. We only have to update the abstraction layer between our views and the framework. And in this case, the abstraction layer is the SCSS file. It's likely to be easier to maintain only that file instead of finding all usages of framework-specific CSS classes across all existing views.
If there's one thing to take away from all of this, it's that isolation principles are valid for every area in our applications.