The “C” in CSS: The Cascade

Following up from Geoff’s intro article on The Second “S” in CSS, let’s now move the spotlight to the “C” in CSS — what we call the Cascade. It’s where things start to get messy, and even confusing at times.

Have you ever written a CSS property and the value doesn’t seem to work? Maybe you had to turn to using !important to get it going. Or perhaps you resorted to writing the CSS inline on the element in the HTML file.

<div style="background:orange; height:100px; width:100px;"> Ack, inline!
</div>

Speaking of inline styles, have you wondered why SVG editors use them instead of a separate CSS file? That seems kinda weird, right?

<svg id="icon-logo-star" viewBox="0 0 362.62 388.52" width="100%" height="100%"> <style> .logo { fill: #ff9800; } </style> <title>CSS Tricks Logo</title> <path class="logo" d="M156.58 239l-88.3 64.75c-10.59 7.06-18.84 11.77-29.43 11.77-21.19 0-38.85-18.84-38.85-40 0-17.69 14.13-30.64 27.08-36.52l103.6-44.74-103.6-45.92C13 142.46 0 129.51 0 111.85 0 90.66 18.84 73 40 73c10.6 0 17.66 3.53 28.25 11.77l88.3 64.75-11.74-104.78C141.28 20 157.76 0 181.31 0s40 18.84 36.5 43.56L206 149.52l88.3-64.75C304.93 76.53 313.17 73 323.77 73a39.2 39.2 0 0 1 38.85 38.85c0 18.84-12.95 30.61-27.08 36.5l-103.61 45.91L335.54 239c14.13 5.88 27.08 18.83 27.08 37.67 0 21.19-18.84 38.85-40 38.85-9.42 0-17.66-4.71-28.26-11.77L206 239l11.77 104.78c3.53 24.72-12.95 44.74-36.5 44.74s-40-18.84-36.5-43.56z"></path>
</svg>

Well, the cascade has a lot to do with this. Read on to find out how styling methods affect what’s being applied to your elements and how to use the cascade to your advantage because, believe me, it’s a wonderful thing when you get the hang of it.

TL;DR: Jump right to the CSS order diagram for a visual of how everything works.

The cascade cares about how and where styles are written

There are a myriad of ways you can apply CSS rules to an element. Below is an example of how stroke: red; can be applied to the same element. The examples are ordered in ascending priority, where the highest priority is at the bottom:

<!-- Inheritance -->
<g style="stroke: red"> <rect x="1" y="1" width="10" height="10" /> <!-- inherits stroke: red -->
</g> <!-- Inline attributes -->
<rect x="1" y="1" width="10" height="10" stroke="red" /> <!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles -->
<style> rect { stroke: red; }
</style> <!-- Different specificity or selectors -->
rect { stroke: red; }
.myClass { stroke: red; }
#myID { stroke: red; } <!-- Inline style -->
<g style="stroke: red"></g> <!-- Important keyword -->
<g style="stroke: red !important"></g>

Inheritance? Embedded? External? Inline? Specificity? Important? Yeah, lots of terms being thrown around. Let’s break those down a bit because each one determines what the browser ends up using when a web page loads.

Elements can inherit styles from other elements

Both HTML and SVG elements can inherit CSS rules that are applied to other elements. We call this a parent-child relationship, where the element the CSS is applied to is the parent and the element contained inside the parent is the child.

<div class="parent"> <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

If we set the text color of the parent and do not declare a text color on the child, then the child will look up to the parent to know what color its text should be. We call that inheritance and it’s a prime example of how a style cascades down to an element it matches… or “bubbles up” the chain to the next matched style.

However, inheritance has the lowest priority among styling methods. In other words, if a child has a rule that is specific to it, then the inherited value will be ignored, even though the inherited value may have an important keyword. The following is an example:

<div class="parent" style="color: red !important;"> <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

See the Pen Child ignores inline inheritance with !important by Geoff Graham (@geoffgraham) on CodePen.

SVG inline attributes

For SVG elements, we can also apply styles using inline attributes, where those have the second lowest priority in the cascade. This means the CSS rules in a stylesheet will be able to override them.

<rect x="1" y="1" width="10" height="10" stroke="red" />
rect { stroke: blue;
}

See the Pen Stylesheet overrides SVG inline attributes by Geoff Graham (@geoffgraham) on CodePen.

Most SVG editors use inline attributes for portability; that is, the ability to copy some elements and paste them elsewhere without losing the attributes. Users can then use the resultant SVG and style its elements using an external stylesheet.

Stylesheets

Stylesheets are divided into two flavors: external and embedded:

<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles -->
<style> div { border: 1px solid red }
</style>

Embedded styles have the same priority as external stylesheets. Therefore, if you have the same CSS rules, ordering rules applies.

See the Pen Embedded styles override stylesheet rules by Geoff Graham (@geoffgraham) on CodePen.

All stylesheets follow ordering rules, where files that are defined later, will have higher priority than those defined earlier. In this example, stylesheet-2.css will take precedence over the stylesheet-1.css file because it is defined last.

<link rel="stylesheet" href="/path/to/stylesheet-1.css">
<link rel="stylesheet" href="/path/to/stylesheet-2.css">

Specificity or selectors

How you select your elements will also determine which rules are applied, whereby tags (e.g. <p>, <div>), classes (e.g. .my-class) and IDs (e.g. #myI-id) have ascending priorities.

See the Pen Specificity by selectors by Geoff Graham (@geoffgraham) on CodePen.

In the example above, if you have a div element with both .my-class and #my-id, the border will be red because IDs have higher priority than classes and tags.

*Specificity has higher priority than ordering rules, therefore, irrespective if your rule is at the top or bottom. Specificity still has higher priority and will be applied.

Ordering

CSS rules always prioritize from left-to-right, then from top-to-bottom.

<!-- Blue will be applied because it is on the right -->
<div style="border: 1px solid red; border: 1px solid blue;"></div> <style> div { border: 1px solid red; border: 1px solid blue; /* This will be applied because it is at the bottom */ }
</style>

Inline styles

Inline styles have the second highest priority, just below the !important keyword. This means that inline styles are only overridden by the important keyword and nothing else. Within inline styles, normal ordering rules applies, from left-to-right and top-to-bottom.

<div style="1px solid red;"></div>

The important keyword

Speaking of the !important keyword, it is used to override ordering, specificity and inline rules. In other words, it wields incredible powers.

Overriding inline rules

<style> div { /* This beats inline styling */ border: 1px solid orange !important; /* These do not */ height: 200px; width: 200px; }
</style> <div style="border: 1px solid red; height: 100px; width: 100px;"></div>

In the example above, without the important keyword, the div would have a red border because inline styling has higher priority than embedded styles. But, with the important keyword, the div border becomes orange, because the important keyword has higher priority than inline styling.

Using !important can be super useful, but should be used with caution. Chris has some thoughts on situations where it makes sense to use it.

Overriding specificity rules

Without the important keyword, this div border will be blue, because classes have higher priority than tags in specificity.

<style> /* Classes have higher priority than tags */ .my-class { border: 1px solid blue; height: 100px; width: 100px; } div { border: 1px solid red; height: 200px; width: 200px; }
</style> <div class="my-class"></div>

See the Pen Classes beat tags by Geoff Graham (@geoffgraham) on CodePen.

But! Adding the important keyword to the tag rules tells the element to ignore the cascade and take precedence over the class rules.

<style> .my-class { border: 1px solid red; } /* The important keyword overrides specificity priority */ .my-class { border: 1px solid blue !important; }
</style> <div class="my-class"></div>

See the Pen !important ignores the cascade by Geoff Graham (@geoffgraham) on CodePen.

Overriding ordering rules

OK, so we’ve already talked about how the order of rules affects specificity: bottom beats top and right beats left. The surefire way to override that is to put !important into use once again.

In this example, the div will take the red border, even though the blue border is the bottom rule. You can thank !important for that handiwork.

<style> div { border: 1px solid red !important; } /* This wins, despite the ordering */ div { border: 1px solid blue; }
</style> <div></div>

See the Pen Important wins over ordering by Geoff Graham (@geoffgraham) on CodePen.

Visualizing the cascade

Who knew there was so much meaning in the “C” of CSS? We covered a ton of ground here and hopefully it helps clarify the way styles are affected and applied by how we write them. The cascade is a powerful feature. There are opinions galore about how to use it properly, but you can see the various ways properties are passed and inherited by elements.

More of a visual learner? Here’s a chart that pulls it all together.

Download chart

The post The “C” in CSS: The Cascade appeared first on CSS-Tricks.

CSS Basics: The Second “S” in CSS

CSS is an abbreviation for Cascading Style Sheets.

While most of the discussion about CSS on the web (or even here on CSS-Tricks) is centered around writing styles and how the cascade affects them, what we don’t talk a whole lot about is the sheet part of the language. So let’s give that lonely second “S” a little bit of the spotlight and understand what we mean when we say CSS is a style sheet.

The Sheet Contains the Styles

The cascade describes how styles interact with one another. The styles make up the actual code. Then there’s the sheet that contains that code. Like a sheet of paper that we write on, the “sheet” of CSS is the digital file where styles are coded.

If we were to illustrate this, the relationship between the three sort of forms a cascade:

The sheet holds the styles.

There can be multiple sheets all continuing multiple styles all associated with one HTML document. The combination of those and the processes of figuring out what styles take precedence to style what elements is called the cascade (That first “C” in CSS).

The Sheet is a Digital File

The sheet is such a special thing that it’s been given its own file extension: .css. You have the power to create these files on your own. Creating a CSS file can be done in any text editor. They are literally text files. Not “rich text” documents or Word documents, but plain ol’ text.

If you’re on Mac, then you can fire up TextEdit to start writing CSS. Just make sure it’s in “Plain Text” mode.

If you’re on Windows, the default Notepad app is the equivalent. Heck, you can type styles in just about any plain text editor to write CSS, even if that’s not what it says it was designed to do.

Whatever tool you use, the key is to save your document as a .css file. This can usually be done by simply add that to your file name when saving. Here’s how that looks in TextEdit:

Seriously, the choice of which text editor to use for writing CSS is totally up to you. There are many, many to choose from, but here are a few popular ones:

  • Sublime Text
  • Atom
  • VIM
  • PhpStorm
  • Coda
  • Dreamweaver

You might reach for one of those because they’ll do handy things for you like syntax highlight the code (colorize different parts to help it be easier to understand what is what).

Hey look I made some files completely from scratch with my text editor:

Those files are 100% valid in any web browser, new or old. We’ve quite literally just made a website.

The Sheet is Linked Up to the HTML

We do need to connect the HTML and CSS though. As in make sure the styles we wrote in our sheet get loaded onto the web page.

A webpage without CSS is pretty barebones:

See the Pen Style-less Webpage by Geoff Graham (@geoffgraham) on CodePen.

Once we link up the CSS file, voila!

See the Pen Webpage With Styles by Geoff Graham (@geoffgraham) on CodePen.

How did that happen? if you look at the top of any webpage, there’s going to be a <head> tag that contains information about the HTML document:

<!DOCTYPE html>
<html> <head> <!-- a bunch of other stuff --> </head> <body> <!-- the page content --> </body> </html>

Even though the code inside the <head> might look odd, there is typically one line (or more, if we’re using multiple stylesheets) that references the sheet. It looks something like this:

<head> <link rel="stylesheet" type="text/css" href="styles.css" />
</head>

This line tells the web browser as it reads this HTML file:

  1. I’d like to link up a style sheet
  2. Here’s where it is located

You can name the sheet whatever you want:

  • styles.css
  • global.css
  • seriously-whatever-you-want.css

The important thing is to give the correct location of the CSS file, whether that’s on your web server, a The Sheet is Not Required for HTML
You saw the example of a barebones web page above. No web page is required to use a stylesheet.
Also, we can technically write CSS directly in the HTML using the HTML style attribute. This is called inline styling and it goes a little something like this if you imagine you’re looking at the code of an HTML file:
<h1 style=”font-size: 24px; line-height: 36px; color: #333333″>A Headline</h1>
<p style=”font-size: 16px; line-height: 24px; color: #000000;”>Some paragraph content.</p>
<!– and so on –>
While that’s possible, there are three serious strikes against writing styles this way: If you decide to use a stylesheet later, it is extremely difficult to override inline styles with the styles in the HTML. Inline styles take priority over styles in a sheet.
Maintaining all of those styles is tough if you need to make a “quick” change and it makes the HTML hard to read.
There’s something weird about saying we’re writing CSS inline when there really is no cascade or sheet. All we’re really writing are styles. There is a second way to write CSS in the HTML and that’s directly in the <head> in a <style> block:
<head> <style> h1 { color: #333; font-size: 24px; line-height: 36px; } p { color: #000; font-size: 16px; line-height: 24px; } </style>
</head>
That does indeed make the HTML easier to read, already making it better than inline styling. Still, it’s hard to manage all styles this way because it has to be managed on each and every webpage of a site, meaning one “quick” change might have to be done several times, depending on how many pages we’re dealing with.
An external sheet that can be called once in the <head> is usually your best bet.
The Sheet is Important
I hope that you’re starting to see the importance of the sheet by this point. It’s a core part of writing CSS. Without it, styles would be difficult to manage, HTML would get cluttered, and the cascade would be nonexistent in at least one case.
The sheet is the core component of CSS. Sure, it often appears to play second fiddle to the first “S” but perhaps that’s because we all have an quiet understanding of its importance.
Leveling Up
Now that you’re equipped with information about stylesheets, here are more resources you jump into to get a deeper understanding for how CSS behaves: Specifics on Specificity – The cascade is a confusing concept and this article breaks down the concept of specificity, which is a method for how to manage it.

  • The latest ways to deal with the cascade, inheritance and specificity – That’s a lot of words, but the this article provides pro tips on how to manage the cascade, including some ideas that may be possible in the future.
  • Override Inline Styles with CSS – This is an oldie, but goodie. While the technique is probably not best practice today, it’s a good illustration of how to override those inline styles we mentioned earlier.
  • When Using !important is The Right Choice – This article is a perfect call-and-response to the previous article about why that method may not be best practice.

  • CSS Basics: The Second “S” in CSS is a post from CSS-Tricks

    The latest ways to deal with the cascade, inheritance and specificity

    The cascade is such an intrinsic part of CSS that they put it right there in the name. If you’ve ever needed to use !important to affect specificity in the cascade, you’ll know that it can be a tricky thing to deal with. In the early days of CSS, it was common to see highly specific selectors like this:

    #sidebar ul li {}

    We’re all much better at managing specificity nowadays. It’s a widely accepted best practice to keep specificity low and flat—to shun ID selectors, to make liberal use of classes, and to avoid unnecessary nesting. But there are still plenty of situations where a more specific selector will be useful. With the introduction of a newly proposed pseudo-class, more support of the shadow DOM, and the use of the all property, we will soon be able to handle inheritance and specificity in new and exciting ways.

    The :is Pseudo-Class

    Lea Verou recently proposed this new pseudo-class specifically designed to control specificity. It’s already made its way to the CSS Level 4 Selectors spec. Lea has a write up of why it’s useful and there’s some coverage of it in the CSS-Tricks almanac.

    Let’s take :not as an example. The specificity of :not is equal to the specificity of its argument. This makes using :not rather painful. Take the following as an example:

    See the Pen :not and specificity by CSS-Tricks (@css-tricks) on CodePen.

    We might expect that the .red class would have higher specificity because it is lower in the cascade. However, for any styles to override div:not(.foobar) they would need to at least match the specificity of a combined element selector (div) and class selector (.foobar). Another approach would be div.red, but there is a better way. This is where :is can help.

    div:is(:not(.foobar)) { background-color: black;
    }

    The :not selector no longer adds any specificity, so the total specificity of the above selector is simply that of one element selector (div). The .red class would now be able to override it in the cascade. Once implemented, specificity hacks will be a thing of the past.

    Shadow DOM

    Today, many people are using classes in HTML like this:

    <form class="site-search site-search--full"> <input type="text" class="site-search__field"> <button type="Submit" class="site-search__button">search</button>
    </form>

    When using shadow DOM, rather than following a verbose naming convention, we’ll be able to omit classes altogether. Styles defined within the shadow DOM are scoped to apply only within the component. Styling can be achieved with simple element selectors without worrying about whether the selectors will interfere with elements elsewhere on the page.

    See the Pen shadow dom by CSS GRID (@cssgrid) on CodePen.

    It’s liberating to write such easy CSS. No more effort spent naming things. Shadow DOM looks like it is finally making its way to full browser support. It’s likely to make it into the next release of Firefox while Edge have implementation as a high priority.

    This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

    Desktop

    Chrome Opera Firefox IE Edge Safari
    53 40 No No No TP

    Mobile / Tablet

    iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
    11.0-11.2 No No 62 62 No

    The all Property

    The all property is a way of setting all CSS properties at once—everything from align-content to z-index. What values does it accept? I can’t think of any use case when I’d want all properties to inherit, but that’s an option. Then there’s initial which is more like applying a CSS reset where all the styles are gone. No padding. No margin. The initial value is set per property, regardless of the element it is applied to. The initial value of display is inline, even if you apply it to a div. The font-style of an em tag is normal, as is the font-weight of a strong tag. Link text will be black. You get the idea. (You can find the initial value of any CSS property on MDN.) This does perhaps limit its usefulness, going further than we might like by removing all styles, regardless of context.

    See the Pen all: initial by CSS GRID (@cssgrid) on CodePen.

    Sadly, the most useful value for all is also the least widely implemented: revert. It can remove the styles that you as a developer have applied, while leaving the default user-agent styles intact. We’ve all seen a page of HTML without a stylesheet—black Times New Roman on a white (transparent) background with blue underlined links. If you really want to avoid inheritance, then all: revert has you covered. All divs will be display: block and spans will be inline. All em tags will be italic and strong tags will be bold. Links will be blue and underlined.

    See the Pen all: revert by CSS GRID (@cssgrid) on CodePen.

    This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

    Desktop

    Chrome Opera Firefox IE Edge Safari
    No No No No No 9.1

    Mobile / Tablet

    iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
    9.3 No No No No No

    The future?


    The miscellany of rival unstandardized methods for writing CSS-in-JS was an attempt to sidestep these same issues. That approach has gained popularity over the last several years. Some of its proponents have deemed inheritance, the cascade and specificity as fundamentally flawed design decisions of the language. The CSS Working Group at the W3C is responding by improving the power of CSS and the native web platform. It will be interesting to see the outcome…


    The latest ways to deal with the cascade, inheritance and specificity is a post from CSS-Tricks