The CSS Cascade, Inheritance, and Specificity
Tags: css, beginners, webdev, tutorial
Published: 2023-08-17 10:16:19

As a beginner diving into the world of web development, one of the fundamental technologies you'll encounter is Cascading Style Sheets (CSS). CSS is the magic behind the beautiful and responsive designs that make websites visually appealing. To become a proficient web developer, it's crucial to understand three key concepts: the CSS cascade, inheritance, and specificity.

## The CSS Cascade

The CSS cascade is the process by which the browser determines which CSS rule will be applied to an element. The cascade works by assigning a weight to each CSS rule and then comparing the weight of each rule to determine which rule should be applied.

These CSS rules can come from various sources which include:

- **User Agent Stylesheets**: These are the default styles applied by web browsers to HTML elements. Different browsers apply different styles depending on the element. For example, each browser styles a range input elements differently.
    
    ```html
    <input id="name" type="range" />
    ```
    
    ![Brave default style for range input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uuen5jz92bfh27rmbton.png)
    
    
    ![Firefox default style for range input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykj9ic4epiqz0pwfva42.png)
    
    
    ![Chrome default style for range input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/su4ak80c7pez1htgijo2.png)
    
    
    ![Microsoft edge default style for range input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5ev8tukv193xe70myqh.png)
    
- **Author Stylesheets**: These are the styles you, the developer, write in your CSS file(s). You define the colors, spacing, and so on. This allows your websites to have consistent design/views across all browsers.
- **User Stylesheets**: These are the styles users apply to websites, which overrides the author's styles. However, this is uncommon among regular web users. Some frontend developers apply these stylesheets either during or after development to see what results could have been achieved.
- **Inline Styles**: These are styles applied using the **`style`** attribute. Inline styles take precedence over external stylesheets.
    
    ```html
    <input id="name" type="range" style="display: none" />
    ```
    

The weight of CSS rules is determined by the following factors:

- **Importance**: CSS provides the **`!important`** keyword to mark certain rules as more important than others. However, it is recommended not to use the **`!important`** keyword as it makes managing your styles more difficult. For example, the heading below will have a red color.
    
    ```css
    h1 {
    	color: red !important;
    }
    
    h1 {
    	color: green;
    }
    ```
    
    ![Red Important](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hoieat9g1s93q0gkyt3f.png)
    
- **Specificity**: Specificity is the algorithm CSS use to determine which rule/property should be applied to an element. More specific selectors take precedence over less specific ones. In short, the more specific a CSS rule is, the higher its weight will be. We'll delve deeper into specificity later.
- **Source order**: If two CSS rules have the same importance and specificity, the rule that appears later in the CSS file will be applied. For example, the previous heading will have a green color cause it comes later in the source order.
    
    ```css
    h1 {
    	color: red;
    }
    
    h1 {
    	color: green;
    }
    ```
    
    ![Green important](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6479hw2h9t7ayr0qwlr.png)   

## Inheritance

Inheritance is a process that allows certain CSS properties to be automatically passed down from a parent element to its child element(s). Think of inheritance as a family tree, where grandparents pass some traits to parents, and parents pass some traits to children. 

However, not all traits from parents are passed to their children. Similarly, not all properties are passed down from parent to child elements. Text properties like `color`, `font`, `line-height`, `opacity` are inheritable, while other properties like `borders`, `padding`, `margin` are not inheritable. 

Here is an example that demonstrates how inheritance works:

```html
<body>
	<h1>Inheritance</h1>
</body>
```

```css
body {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100vh;
	color: coral;
	font-family: 'Courier New', Courier, monospace;
	border: 1px solid green;
}
```

![Inheritance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewbddzqo1c61ckasr104.png)

In the above example, notice that the `h1` inherits the `color` and `font-family` properties from its parent, `body`, but it doesn’t inherit other properties. Specifying the same `font-family` on the `h1` isn’t necessary due to inheritance. Knowing which properties inherit and which don't can save you from unnecessary duplication of style declarations.

```css
h1 {
	font-family: 'Courier New', Courier, monospace; // not necessary
}
```

While some properties are inherited by default, you can use the **`inherit`** keyword to explicitly inherit any parent property. From the previous example, if we want the **`<h1>`** to inherit the parent's border, we can do so like this:

```css
h1 {
	border: inherit;
}
```

![Inherited border](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9mcmzbo1mrkw2m7qrzf.png)

## Specificity

Specificity is a method used to determine which CSS rule should be applied to an element in situations where conflicting rules exist. It involves assigning a weight to different CSS rules to determine which one is the most specific and therefore takes precedence.

Specificity is calculated using various selectors, which are organized in order of decreasing specificity:

- `id selector`: Styling by `id` is more specific than any other selector. Think of `id` as the king of a village. You can only have a king in a village, which means you can only have a unique `id`.
    
    ```css
    #myId {
    	color: red;
    }
    ```
    
- `class selector`: This selector includes classes like `.myClass`, attributes like `[type="search"]`, and pseudo-classes like `:hover`. No matter the number of class selectors combined, they will never override an id selector. Think of them as the queens within a village.
    
    ```css
    .myClass {
    	color: brown;
    }
    ```
    
- `Type selector`: This selector includes HTML tags like `div`, `table`, `section` and pseudo-elements like `::before` and `::placeholder`. Think of them as the heirs of a village.
    
    ```css
    section {
    	color: yellow;
    }
    ```
    
- `Universal selector`: This selector matches all elements of any type. It is denoted by `*`. It does not impact the specificity value in any way.
    
    ```css
    * {
    	color: coral
    }
    ```
    
    In the absence of all selectors, all elements on a page will have a coral color. The universal selector is commonly used to reset the `padding`, `margin` and `box-sizing` of all elements on a page.
    
    ```css
    * {
    	padding: 0;
    	margin: 0;
    	box-sizing: border-box;
    }
    ```
    

## **Combining Selectors and Calculating Specificity**

You might be wondering, what happens when these selectors are combined? When selectors are combined, their specificity values are also combined. Specificity is usually represented as a three-component value: **[a, b, c]**. These components represent the specificity of ID selectors, class selectors, and type selectors, respectively.

For example, let's say we have the following selectors on this element:

```html
<section id="myId" class="myClass anotherClass">
	Hello
</section>
```

```css
#myId.myClass {
    color: purple;
}

section#myId.myClass {
	color: orange;
}

#myId.myClass.anotherClass {
	color: orange;
}

section#myId.myClass.anotherClass {
	color: brown;
}

section.myClass.anotherClass {
	color: orange;
}

section {
	color: blue;
}
```

In this scenario, each specificity here is:

- `myId.myClass`: `[1, 1, 0]`
- `section#myId.myClass`: `[1, 1, 1]`
- `#myId.myClass.anotherClass`: `[1, 2, 0]`
- `section#myId.myClass.anotherClass`: `[1, 2, 1]`
- `section.myClass.anotherClass`: `[0, 2, 1]`
- `section`: `[0, 0, 1]`

We will follow the following process to determine which specificity prevails:

1. First, eliminate any of the specificity without an `id`. This leaves us with `myId.myClass`, `section#myId.myClass`, `#myId.myClass.anotherClass` and `section#myId.myClass.anotherClass`.
2. Then, pick the ones with the highest number of class selectors. This leaves us with `#myId.myClass.anotherClass` and `section#myId.myClass.anotherClass`. Notice that even though `section#myId.myClass` has another selector, we discarded it because a `class selector` is always greater than `type selector` no matter the number of type selectors.
3. Lastly, pick the one with the highest number of type selectors. This leave us with `section#myId.myClass.anotherClass` which means that `section` will have a brown color.


![Specificity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19gziq3h38s1n4g7qxhj.png)

## Combining the three: The CSS Cascade, Inheritance and Specificity

To combine these three concepts, consider the following example:

```html
<section id="parent">
	<header class="child">
		<h1 class="grandchild">Hello, World!</h1>
	</div>
</div>

```

```css
#parent {
	background-color: red;
}

.child {
	background-color: blue;
}

.grandchild {
	color: white;
}

```

The CSS rules above will apply a red background color to the parent `section`, a blue background color to the child `header`, and a white color to the text of the grandchild `h1`.

If you change the color of the grandchild to black, it will override the parent and child rules because it has a higher specificity. Similarly, if you change the background color of the child to green, it will override the parent rule because it has the same specificity but comes later in the cascade.

```css
#parent {
	background-color: red;
}

.child {
	background-color: blue;
}

.grandchild {
	color: white;
}

.child {
	background-color: green;
}
```

Finally, if you add an `!important` keyword to the child's background color, it will override all other rules regardless of their specificity or position in the cascade.

```css
#parent {
	background-color: red;
}

.child {
	background-color: blue;
}

.grandchild {
	color: white;
}

.child {
	background-color: green;
}

header {
	background-color: aqua !important;
}
```

It's important to keep these concepts in mind when writing CSS to ensure that your styles are applied as intended and that you can easily manage and maintain your codebase.

## Conclusion

To summarize, understanding the CSS cascade, inheritance, and specificity is crucial to becoming a proficient web developer.

- The cascade determines which CSS rule will be applied to an element.
- Inheritance allows certain CSS properties to be passed down from a parent element to its child element(s).
- Specificity determines which CSS rule should be applied to an element in situations where conflicting rules exist.
- `!important` should be a last resort.
- Avoid combining multiple selectors. e.g `section#myId.myClass.anotherClass`
- Avoid `id selector`, instead use other selectors like `class`.

By mastering these concepts, you can write efficient and maintainable CSS code for your web projects.

## Helpful links:

- [**Learn more about CSS Cascade on MDN**](https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade)
- **[Learn more about CSS specificity on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity)**
- **[Learn more about !importance on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/important)**