Direct > Descendant > CSS

Alex Bennett 24 October 2017

I have read a lot on the subject of modern CSS performance, there is a huge discussion as to the best method of creating a performant and maintainable codebase for styles. I have tried several methods myself, back in the days before build tools I was used to writing out plain old CSS but now we can nest with SASS/LESS! This has allowed us to write less code overall for the same effects, which is great, but it also encourages some bad practices if people get lazy.

I have been playing around with ways to keep a codebase maintainable for a while now - when it comes to small creative projects the amount of styling involved is often negligible but for large sites with multiple components and a raft of UI differences depending on use cases it’s important to keep things neat and obvious for the next developer.

Here in lies a problem, we all develop sites differently, we all have our own ways of working and structuring things - we have our own way of naming things too, so things can get problematic fast.

BEM is a way around this, it attempts to give your naming convention a meaning - but only works if you really stick to it, and can result in some really ugly selector names. There are many schools of thought out on the subject of style maintainability and structuring. I fully endorse the atomic way of thinking, as with my modular ES6 JavaScript I compartmentalize all my styles when writing SASS. When it comes to naming conventions I prefer my selectors to be ubiquitous, it requires less mental effort when reading through again or matching up with the markup if all components are named the same way.

As a small example, I am a big fan of all navigation elements in a UI being semantically valid, so a menu for me is a ul with nested li containing anchors - some methods would have you globalise what styles you could, maybe on the ul itself, but in my experience a menu in one component may be entirely different in styling than a menu in another component, but why create multiple selector names to juggle for the same “thing”. So I like my ul to have a class of “items”, my li are “item” and my anchors are “link”. This naming convention is simple, descriptive and relevant no matter where it is.

So how do I get around overriding styles you may be thinking! The answer here is the descendant selector, now this does break the 4 nesting rule in almost all cases, some people probably hate that. Here is a good write up about the Inception Rule, I know what they are saying about performance and file size but for the benefit DDS-CSS has given me it seems negligible. Especially in a world of caching and CDN’s.

There was a brief discussion on CSS Tricks a while ago, I specifically want to pick out one comment here.

MattDiMu makes a good point, and he’s right… who does do that?! Well. That’s what this post is about because I am indeed crazy enough to write all my styles (for the most part) as direct descendants.

I see no issues with this method in terms of performance given browsers read styles from right to left when painting. And the benefit of only using direct descendant is you can make your markup specific to each component without juggling a million selectors.

All ul are “items”, all li are “item” and all anchor are “link” - nice and easy, here is an example of a direct descendant component.

.component–search-results {  @include paddings;    > .column {   @include as-generic-content-column;   @include as-paddings–generic-content   background-color: $cs-white;     > .results {    list-style: none;    padding: 0;    margin: 0;      > .item {     margin-bottom: 25px;     border-bottom: 1px solid #cbcbcb;       > .link {      > .title {       @include as-font-normal-title;       margin: 10px 0 20px;         > * {        font-size: inherit;       }      }        > .excerpt {       margin-bottom: 25px;      }     }       &:last-of-type {      border-bottom: none;      margin-bottom: 0;     }    }   }  }    @media (min-width: $px-width-tablet) {   > .column {    > .results {     > .item {      margin-bottom: 40px;        > .link {       > .excerpt {        margin-bottom: 40px;       }      }     }    }   }  } }

The style layout matches the HTML perfectly, this guarantees us an additional check when the site is being integrated with the CMS. If a backend developer makes a mess of our markup when wiring things up then its immediately spottable because the styles fall apart.

The method tightly couples the way you write your markup and the way you arrange your styles. It has at times forced me to really think about how I am going about building something - and often times saved me a headache down the line or the requirement to add a dodgy style somewhere that has a far-reaching tree for the browser to search through when painting.

I haven’t found anything specific to this method written up before so if it sounds interesting and worth spending more time to create some performance comparisons get in touch and let me know!


If you have an interesting opportunity or a project in need of a developer, please get in touch: