Chapter 1.3.2 - The Cascade and Combining Selectors


The Cascade

Within CSS, all styles cascade from the top of a style sheet to the bottom, allowing different styles to be added or overwritten as the style sheet progresses.

For example, say we select all paragraph elements at the top of our style sheet and set their background color to orange and their font size to 24 pixels. Then towards the bottom of our style sheet, we select all paragraph elements again and set their background color to green, as seen here.

p {
	background: orange;
	font-size: 24px;
}
p {
	background: green;
}

Because the paragraph selector that sets the background color to green comes after the paragraph selector that sets the background color to orange, it will take precedence in the cascade. All of the paragraphs will appear with a green background. The font size will remain 24 pixels because the second paragraph selector didn’t identify a new font size. >The cascade also works with properties inside individual selectors. In the following example, the green property takes precedence over the orange.

p {
	background: orange;
	background: green;
}

If you want to make sure that some value won't be overwritten by another value, use !important key after the value (i.e., background: orange !important).

Selector Specificity Weight

Every selector in CSS has a specificity weight. A selector’s specificity weight, along with its placement in the cascade, identifies how its styles will be rendered.

You've learned about three types of selectors: type, class, and ID. A selector's specificity is calculated using three columns. They are outlined below as follows:

selectorweight
type0-0-1
class0-1-0
ID1-0-0

The first column counts ID selectors, the second column counts class selectors, and the third column counts type selectors. The ID selector has a higher specificity weight than the class selector, and the class selector has a higher specificity weight than the type selector. The higher the specificity weight of a selector, the more superiority the selector is given when a styling conflict occurs.

For example, if a paragraph element is selected using a type selector in one place and an ID selector in another, the ID selector will take precedence over the type selector regardless of where the ID selector appears in the cascade.

HTML

<p id="food">...</p>

CSS

#food {
	background: green;
}
p {
	background: orange;
}

In the above example we have a paragraph element with an ID attribute value of food. Within our CSS, that paragraph is being selected by two different kinds of selectors: one type selector and one ID selector. Although the type selector comes after the ID selector in the cascade, the ID selector takes precedence over the type selector because it has a higher specificity weight; consequently the paragraph will appear with a green background.


Combining Selectors

By combining selectors we can be more specific about which element or group of elements we’d like to select. For example, say we want to select all paragraph elements that reside within an element with a class attribute value of hotdog and set their background color to brown. However, if one of those paragraphs happens to have the class attribute value of mustard, we want to set its background color to yellow.

HTML

<div class="hotdog">
	<p>...</p>
	<p>...</p>
	<p class="mustard">...</p>
</div>

CSS

.hotdog p {
	background: brown;
}
.hotdog p.mustard {
	background: yellow;
}

When selectors are combined they should be read from right to left. The selector farthest to the right, directly before the opening curly bracket, is known as the key selector. The key selector identifies exactly which element the styles will be applied to. Any selector to the left of the key selector will serve as a prequalifier.


Spaces Within Selectors

Since there isn’t a space between the paragraph type selector and the mustard class selector that means the selector will only select paragraph elements with the class of mustard. If the paragraph type selector was removed, and the mustard class selector had spaces on both sides of it, it would select any element with the class of mustard, not just paragraphs. The best practice is to not prefix a class selector with a type selector. Generally we want to select any element with a given class, not just one type of element. And following this best practice, our new combined selector would be better as .hotdog .mustard.


Reading the combined selector from right to left, it is targeting paragraphs with a class attribute value of mustard that reside within an element with the class attribute value of hotdog.

Specificity Within Combined Selectors

When selectors are combined, so are the specificity weights of the individual selectors. These combined specificity weights can be calculated by counting each different type of selector within a combined selector >Looking at our combined selectors from before, the first selector, .hotdog p, had both a class selector and a type selector. Knowing that the point value of a class selector is 0-1-0 and the point value of a type selector is 0-0-1, the total combined point value would be 0-1-1, found by adding up each kind of selector.

In general we want to always keep an eye on the specificity weights of our selectors. The higher our specificity weights rise, the more likely our cascade is to break.

Layering Styles with Multiple Classes

To keep the specificity weights of our selectors low we should consider being as modular as possible by sharing similar styles from element to element . We layer on different styles by using multiple classes.

Elements within HTML can have more than one class attribute value so long as each value is space separated. With that, we can place certain styles on all elements of one sort while placing other styles only on specific elements of that sort.

HTML

<a class="btn color-danger">....</a>

<a class="btn colorr-success">...</a>

CSS

.btn {
	font-size: 16px;
}
.color-danger {
	background: red;
}
.color-success {
	background: green;
}

In the above example, we want our buttons to have a font size of 16 pixels; however, we want the background color of our buttons to vary depending on where the buttons are used. We create a few classes and layer them on an element as necessary.