Mastering the Cascade

The first letter of CSS stands for “cascading” – and it does so for a reason. Contrary to what many developers might say, the cascade is a useful feature. Not a bug. Not a reason CSS is “broken”. Using and understanding the cascade is paramount to really mastering CSS.

I’m going to help explain the cascade and its usefulness in 3 points:

  1. What it is
  2. How to use it
  3. How to break out of it when needed

This is less a “how to” article, and more of a conceptual article, as I feel that most devs know the how, but not the why of a lot of front end dev – which leads to terrible ideas like CSS in JS…but that’s an article for another day!

What is the cascade?

Let’s imagine CSS as a cascading (pun intended!) waterfall. The water at the top of the waterfall falls down to the bottom of the pool, touching everything on the way down. the water at the bottom of the pool doesn’t touch or effect the water on top. Similarily, CSS is read top to bottom, with selectors at the top of the file affecting similar selectors at the bottom. For example, if we had the rule:

p { 
     font-size: 18px;
}

at the top of the file, every single paragraph below this rule will inherit the 18px font size, unless we declare a different size later on (see later section on breaking our of the cascade).

How to use it

Most developers understand what the cascade is, but don’t understand how to use it to their benefit. If we know that some properties will also have the same styles, for example that all H1s on the site will be blue and 50px, it helps to declare this one time only. It allows us to make changes in one place, instead of on every single h1 declaration. It also keeps our CSS clean, short, and precise, making for smaller file sizes and easier for another dev to update.

It’s best to have the least amount of repetition as possible, within reason. So use the cascade to style properties once and know when to break out of the cascade for unique properties.

Many naysayers of the cascade claim that inheriting properties actually creates more issues and redundancy than it helps. This is untrue. While you may have a site with several different styles for the same element, like headings and buttons, I still believe the cascade is important for setting a baseline, in case someone adds a property out of place somewhere in the HTML, or something that forgets to get styled. For an example, I’ll usually set baseline styles for buttons. I’ll have a default style named “.btn” and then I’ll add modifier classes for slightly different styles, like “orange” or “white-fill”.

.btn { 
     background: blue;
     color: #fff;
     font-size: 18px;
     padding: 10px 20px;
}
 
.btn.white-fill {
     background: #fff;
     color: blue;
}
 
.btn.orange {
     border: 2px solid orange;
}

The buttons all get the initial styles, but are modified by the CSS that comes after is. This is working with the cascade and allows for cleaner, reusable code.

Breaking out of the cascade

Breaking out of the cascade is easy – we simply become more specific with our selectors and redeclare our properties. For example if we have links styled as red with an underline, but in a specific module we need them to be black and underlined, we simply either add a class to the link or use a containing element to make our CSS more specific, overwriting the baseline style:

a {
     color: red;
     text-decoration: underline;
}
 
.example a { 
     color: #000;
}

We’ve only redeclared the color here, so the link will still inherit the original text underline.

This is what trips some developers up – an element from high up in the stylesheet affecting an element hundreds of lines down, which can cause unexpected issues. The issue is usually due to specificity as being too specific in our selectors means it’s harder to restyle them later when needed. You can technically be as specific as you want when styling your HTML, following the tree all the back to the <HTML> tag, but this is a terrible thing to do. You should always try to declare the least specific selectors as possible. Selectors are read from the right to left, so in the above example, the browser would find all of the <a> links first, and then it would look for the <a> links inside of an element with the class of “example”. So stringing several selectors together not only affects loading time and resources, it makes it harder to restyle later on, leading to unexpected behavior. So don’t use body header ul li a when header a or header li a will just fine.

NOTE: I’m very well aware of those of us who have to break these rules when styling HTML we have no control over and already have specific CSS styles applied (I’m looking at YOU WordPress plugins!), especially when the plugin’s CSS is added below your own. I didn’t say the cascade was awesome all the time!

Another way to cut down on specificity issues, is to use classes instead of IDs, since IDs are ranked as more specific than classes. CSS Tricks has a fantastic article on learning about CSS specificity and selectors.

What about !important?

Using !important is generally advised against, as it overwrites all specificity and can create confusion down the line, when you’re just trying to change your dang buttons to blue and be done with it. But like all rules, there’s always exceptions. Working with elements that have styles applied to them that we can’t change (those plugins again!) comes to mind. My “favorite” thing to do is trying to figure out how many classes I need to chain together to get WooCommerce to read my CSS instead of its own. Fun!

Another time I personally use !important, is during responsive design. If you have items that use nth-of-type, nth-child, or any of those pseudo variances, you’ll have to relist those selectors every time you want to make a change to the main styles, so they’ll affect those as well, I do admin to using !important here to avoid having to do this several times:

.post {
     margin-right: 20px;
     width: 200px;
}
 
.post:nth-of-type(3n) {
     margin-right: 0;
}
 
.post:nth-of-type(3n+4) {
     margin-right: 10px;
}
 
/*Later on in a media query*/
 
.post {
     margin: 0 10px !important; /*overwrites previous .post:nth-of-types*/
}

I know this technically wouldn’t be an issue if I was coding for mobile first, but I’m usually only given the desktop designs from the designer and have to code the mobile versions off of those on my own. But you get the idea. There’s always an exception to everything,

So what?

Working with the cascade can have some drawbacks, but it’s an important part of CSS and a powerful feature. Using it properly makes your code cleaner and easier to maintain. It cuts down on repetition and helps to ensure all elements are styled. While you may end up overwriting some of the rules, that doesn’t mean it’s broken or a useless feature. Without it, we’d be forced to repeat rules over and over again, repeating ourselves each time.