Object oriented CSS manifest

I have been developing websites since 1999 and took part in various evolutionary steps of HTML as well as CSS over the years. With the introduction of HTML5 my focus began to slowly shift from backend to frontend. As of today I would say that my personal transition has come, more or less, to an end. Sure, I still do backend at a very high level and keep up to date technologically - but my passion really became what is known as "user experience" in combination with semantic use of HTML in regards to accessibility and SEO.

I, like many others, constantly try to optimize what I do, try to simplify my code to make it faster, easier to maintain, more DRY or enhance OOP capabilities.

There are very elegant and completely sufficient approaches to solve OOP and inheritance in JavaScript and most other programming/script languages relevant for our field of work. But as a developer I tend to transfer concepts from one language to the other. But what about transferring OOP/inheritance to CSS?

Existing OOCSS solutions

As far as I know Nicole Sullivan, widely known as Stubbornella1, was the first to officially talk about what she called OOCSS. Soon after that the BEM2 methodology was invented by Yandex and introduced a quite sophisticated approach using multiple classes which allowed for great flexibility without the dangers of single selectors being overwritten.

Although the overall BEM approach is really great and able to solve all relevant real world problems I admit I never liked it. The simple reason is that I personally dislike the accompanying need to have enormous class names spread all over my otherwise clean & neat HTML code.

I began to do some research for better suiting alternatives and came across Attribute Modules3 which I analyzed with great interest. It sure is a very good alternative allowing for much leaner HTML that also solves many of the issues BEM already did. I only found one drawback that makes it not sufficient in my eyes: Block and element (the "B" and "E" of the BEM methodology) are both part of the attribute name. What this implies is that the value of the element is only allowed to contain the modifiers. Because of the way how CSS works in this respect it implies that you will not be able to have any kind of inheritance using Attribute Modules. A major drawback in my eyes - in case you are required to have inheritance that is.

Back to the drawing board

So I thought about the things I have been playing with over the last couple of months and if they could be of any use for this matter. What came to my mind ist that the central problem all existing solutions have to cope with is the introduction of scoping to the otherwise unscoped CSS world. This did immediately remind me of what microdata4 does to HTML. Just to give you a very simple example and an idea of how microdata looks like:

<figure itemscope itemtype="http://schema.org/ImageObject">
    <img src="[url]" alt="[alt-text]" itemprop="contentUrl" />
</figure>

So what microdata actually does is to give you some more structural properties, mostly for SEOs sake. What really only is required to make the "itemprop" attribute validate correctly is the "itemscope" attribute of the surrounding figure element. The "itemtype" is only a reference or hint to the type of object you are using and is not strictly required.

For "itemscope" having no value at all I first thought about simply putting some type of scope in its value. Although this is absolutely possible from a technical point of view this indeed will not validate (but might still be an option according to Attribute Modules also proposing "am-" attributes not validating correctly). But even if I have to use a custom "data-scope" attribute (which would also make the solution independent of microdata) this can still be the way to go.

Just as a sidenote: I still like to use microdata where applicable because its "itemprop" properties allow me to untie my CSS from the actual HTML structure adding the benefit of using microdata without any extra hazzle.

So what do I put in this freaky "data-scope" attribute?

The content "blocks" from my website represent a very good use case. Just to give you some insight:

The content area of my site consists of any number of "block" elements that contain independent content. The default block has a grey background color and light text color. All other colors can safely inherit from this block and only need to override the background as well as the text color where necessary. Simple and classical inheritance. The blocks have a number of modifiers for the actual width of the block or more special cases like a fixed height or making a block "chromeless" (meaning having no padding at all) which should be shared between all type of blocks. So what I ended up with in my HTML looks something like this:

<section class="small fixed" data-scope="/block">
    ... some narrow content ...
</section>

<section class="medium fixed" data-scope="/block/purple">
    ... some medium content ...
</section>

And the relevant CSS (or LESS in my case) to solve the inheritance looks somewhat like:

[data-scope^="/block"] {
    /* styles shared between all types of blocks */

    &[data-scope*="/purple"] {
        /* styles specific for the "purple" block */
    }

    &.medium {
        /* styles for all type of medium blocks */
    }

    &.fixed {
        /* styles for all type of fixed blocks */
    }
}

The CSS/LESS uses what is known as attribute selectors which were introduced back with IE7! As you can see I could easily implement further inheritance for something like "/block/purple/light" or anything alike. In this case I left the modifiers within the class attribute. I did this because on my site I, as the only developer, can guarantee that there will be no naming conflicts. But even if I could not I could easily move the modifiers from the class attribute into the data-scope attribute like this:

<section data-scope="/block small fixed">
    ... some narrow content ...
</section>

<section data-scope="/block/purple medium fixed">
    ... some medium content ...
</section>

And match them with a slightly modified (and slightly larger) CSS/LESS:

[data-scope^="/block"] {
    /* styles shared between all types of blocks */

    &[data-scope*="/purple"] {
        /* styles specific for the "purple" block */
    }

    &[data-scope~="medium"] {
        /* styles for all type of medium blocks */
    }

    &[data-scope~="fixed"] {
        /* styles for all type of fixed blocks */
    }
}

So what this approach combines is a kind of object orientation allowing for any level of inheritance and any number of modifiers plus being able to scope wherever you and/or your project require. I cannot currently think of any drawbacks it introduces and will continue to use and improve it myself. Feel free to use it on your own behalf as well, and help spread the word if you do!

I would honestly love to get some shared thoughts on this approach to further improve it