Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 106 additions & 54 deletions docs/css/basics/cascading-order.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,95 +5,147 @@ description: "Understand the three core principles (C-S-I) that determine which
keywords: [CSS Cascade, CSS Specificity, CSS Inheritance, Rule Conflict, Important rule, important, CodeHarborHub CSS]
---

You now know three different places to put your CSS: **Inline**, **Internal**, and **External**. But what happens when you set an element's color to blue in an external file and then try to set it to red using an internal style?
You now know there are three ways to write CSS: Inline, Internal, and External. But what happens when you accidentally apply **two different styles** to the same element?

The browser uses three fundamental principles, often called the **C-S-I** (Cascade, Specificity, Inheritance), to decide which rule wins and is actually applied. This is the **most crucial concept** in CSS.
The browser doesn't guess; it uses a strict set of rules known as the **Cascade** to determine which style wins. The Cascade is the process that combines three core concepts to resolve conflicts and apply the final styles:

## 1. The Cascade: Where Does the Style Come From?
1. **The Cascade:** Where does the style come from?
2. **Specificity:** How detailed is the selector?
3. **Inheritance:** Does the element automatically get its parent's style?

The **Cascade** determines the order in which CSS rules are processed and how conflicts are resolved based on the **source and order** of the styles.
## 1. The Cascade: Order and Source

In a conflict, the browser looks at the following sources, in order of increasing importance:
The **Cascade** is the primary system for layering styles. It decides the initial winner based on the origin and order of the stylesheet.

### A. Origin and Importance (The !important Rule)
### Source Order (The "Where" of the Style)

| Order | Source | Description |
Styles are prioritized based on their source. Think of it as a river flowing downhill—styles closer to the element tend to flow last and have more power:

| Priority | Source | Description |
| :--- | :--- | :--- |
| **1 (Lowest)** | Browser Defaults | The default styling applied by the browser (e.g., links are blue and underlined). |
| **2** | User Stylesheets | Styles set by the user (rare, used for accessibility purposes). |
| **3** | Author Stylesheets | **Your code** (External, Internal, and most Inline styles). |
| **4 (Highest)** | `!important` | Any rule followed by `!important` overrides almost everything else. **Avoid using this** unless absolutely necessary, as it breaks the natural flow of the cascade. |
| **Highest** | **User Styles** (High Specificity) | Styles applied directly by the user (e.g., accessibility settings). |
| **2nd Highest** | **Author's Styles** (`!important`) | Any rule in your CSS file marked with `!important`. |
| **3rd Highest** | **Author's Styles** (Normal) | **Your External, Internal, and Inline styles** (where Specificity rules the day). |
| **Lowest** | **Browser Default Styles** | Default styles set by the browser (e.g., blue links, large `<h1>`). |

### B. Order of Appearance
### **The Role of Order:**

If two rules have the exact same **Origin** (e.g., both are in your external file) and the same **Specificity** (covered next), the rule that appears **later** in the stylesheet or the HTML document **wins**.
If two rules have the exact same Specificity (we'll cover this next) and come from the same source (e.g., two rules in your external stylesheet), the **last rule defined wins**.

```css title="styles.css"
/* Rule 1 appears first */
p { color: red; }

/* Rule 2 appears later and has the same specificity, so it wins */
p { color: blue; }
/* The paragraph will be blue. */
````
p { color: blue; } /* This rule is defined first. */
p { color: red; } /* This rule is defined last, so all <p> text will be RED. */
```

## 2. Specificity: Who is More Precise?

When multiple rules target the same element, **Specificity** is the unique score assigned to a CSS selector that determines which rule is applied. The selector with the **higher score always wins**, regardless of the order it appears in the stylesheet.
When two or more selectors try to style the same element, the browser calculates which selector is **more specific**. The selector with the highest specificity score always wins, regardless of where it appears in the CSS file (unless it's overridden by `!important`).

### Specificity Scoring
Specificity is calculated by counting different types of selectors. Think of it as a four-digit number $(A, B, C, D)$, where the highest number in the most significant column wins.

Specificity is calculated using a four-digit number, often written as `(A, B, C, D)`.
### Specificity Score Breakdown

| Category | Score | Example | Notes |
| Letter | Selector Type | Example | Value |
| :--- | :--- | :--- | :--- |
| **A: Inline** | 1000 | `<p style="color: red;">` | Always wins over non-inline styles. |
| **B: IDs** | 100 | `#main-header` | A unique identifier. |
| **C: Classes, Attributes, Pseudo-classes** | 10 | `.card`, `[type="text"]`, `:hover` | Includes most common selectors. |
| **D: Elements, Pseudo-elements** | 1 | `p`, `h1`, `::before` | The lowest score. |
| **A** | **Inline Styles** | `<div style="...">` | **1000** |
| **B** | **IDs** | `#main-nav` | **100** |
| **C** | **Classes, Attributes, Pseudo-classes** | `.card`, `[type="text"]`, `:hover` | **10** |
| **D** | **Elements and Pseudo-elements** | `p`, `div`, `::after` | **1** |

### Specificity Example

Let's look at a common conflict:
Let's compare two conflicting selectors:

| Selector | Calculation | Specificity Score |
| :--- | :--- | :--- |
| `h1` | (0, 0, 0, 1) | **1** (Element) |
| `.page-title` | (0, 0, 1, 0) | **10** (Class) |
| `#header h1` | (0, 1, 0, 1) | **101** (ID + Element) |
| Selector | Score (A, B, C, D) | Total | Result |
| :--- | :--- | :--- | :--- |
| `h1` | (0, 0, 0, 1) | 1 | **Loses** |
| `.header-title` | (0, 0, 1, 0) | 10 | **Wins** (The class is 10 times more specific than the element.) |

| Selector | Score (A, B, C, D) | Total | Result |
| :--- | :--- | :--- | :--- |
| `#sidebar p` | (0, 1, 0, 1) | 101 | **Wins** |
| `.card .title` | (0, 0, 2, 0) | 20 | **Loses** (ID selector is 100 points, dominating the score.) |

**Result:** The style from `#header h1` will win and be applied, even if `.page-title` appears after it in the CSS file, simply because **101 is greater than 10**.
:::tip Specificity Tip
Never use Inline Styles and try to reserve **ID selectors** (`#`) for JavaScript targeting rather than styling, as their high specificity makes CSS harder to override and maintain.
:::

## The Power of `!important`

The `!important` keyword is the nuclear option of CSS. When added to a declaration, it instantly makes that style rule **override all other rules**, regardless of specificity.

```css title="styles.css"
/* This style will win over any ID, Class, or Element selector */
p {
color: green !important;
}

:::tip Analogy
/* Even if an ID tries to override it, the !important rule wins */
#main-content p {
color: red; /* This will be ignored */
}
```

Specificity is like a bidding war. An **Inline Style** is a million dollars (1000). An **ID** is a thousand dollars (100). A **Class** is a hundred dollars (10). Whoever bids more wins!
:::danger When to Avoid `!important`

**Avoid using `!important`!** It breaks the natural cascade flow and specificity rules, making your code extremely difficult to debug and maintain. Only use it in rare cases like:

1. Overriding third-party library styles where you can't edit the source CSS.
2. Utility classes (e.g., `.u-hidden { display: none !important; }`).

:::

-----
## 3. Inheritance: Borrowing Styles from Parents

The final piece of the puzzle is **Inheritance**. Certain CSS properties are passed down (inherited) from a parent element to its child elements.

### Inherited Properties

Properties related to **text** and **typography** typically inherit:

* `color`
* `font-family`
* `font-size`
* `line-height`
* `text-align`

### Non-Inherited Properties

Properties related to the **Box Model** and **Layout** do **not** inherit:

* `margin`
* *`padding`*
* `border`
* `width` / `height`
* `background-color`

### Inheritance Example

## 3. Inheritance: Passing Down the Genes
```html title="index.html"
<div style="font-family: Georgia, serif; border: 1px solid black;">
<p>This paragraph inherits the font from its parent <div>.</p>
<p style="border: none;">But it DOES NOT inherit the border or padding.</p>
</div>
```

**Inheritance** is the third principle, determining how styles flow down the document tree from parent elements to their children.
The browser applies the `font-family` to the `<p>` elements, but since `border` is not inherited, the `<p>` tags will not have a border unless one is specifically declared for them.

Some properties are naturally **inherited** (passed down), while others are not.
## Interactive Cascade Order Demo

### Properties that Inherit
This interactive example shows how **Specificity** (ID vs. Class) and **Source Order** (last rule wins) determine the final style.

* **Text and Font properties** generally inherit: `color`, `font-family`, `font-size`, `line-height`, `text-align`.
* If you set the `font-family` on the `<body>` element, all paragraphs and headings inside the `<body>` will automatically use that font.
In the CSS panel, try changing the color values and observe which rule wins based on the selector's power.

### Properties that Do Not Inherit
<CodePenEmbed
title="Interactive Cascade Order Demo"
penId="MYyyqpB"
/>

* **Box Model properties** generally do not inherit: `margin`, `padding`, `border`, `width`, `height`.
* If you set a `border: 2px solid black;` on the `<div>`, its child elements will *not* automatically get that border. This makes sense, as you wouldn't want every nested element to inherit its parent's spacing\!

### Controlling Inheritance
### Observations

You can force any property to inherit or not using these special keywords:
1. The first paragraph's color is **Purple** because the **ID selector (`#intro-paragraph`)** has the highest Specificity score (100), overriding the Class (`.main-text`, score 10) and Element (`p`, score 1) selectors.
2. The `font-weight` is **Bold** because it is set by the Class selector (Rule 2), and the ID selector (Rule 3) does not attempt to change the `font-weight`, allowing the inherited property to apply.
3. The second paragraph (which has no class or ID) should take the color of the **last `p` rule defined in the CSS** if they were the only ones present. However, because the class and ID rules are present, they dominate the first paragraph.

| Keyword | Purpose |
| :--- | :--- |
| `inherit` | Forces a child element to take the computed value of the parent element (even if it normally wouldn't inherit). |
| `initial` | Resets the property to its default browser value. |
| `unset` | Resets the property to either the inherited value (if it's an inherited property) or the initial value (if it's not). |
**The Cascade is a complex dance of Specificity first, and Source Order second.**
9 changes: 9 additions & 0 deletions docs/css/basics/external.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,12 @@ The Cascade is more complex, involving **Specificity** (which we'll cover in a f
| **Inline** | Inside the element's `style` attribute. | No | Single element, quick debugs, HTML emails. |
| **Internal** | Inside the `<style>` tag in the `<head>`. | No (Requires Copy/Paste) | Single, standalone demos or test pages. |
| **External** | In a separate linked `.css` file. | Yes | **All modern, multi-page websites.** |

### Interactive External Styles Demo

Use the live editor to change the styles and watch the change below.

<CodePenEmbed
title="Interactive External Styles Demo"
penId="WbwwKJG"
/>
2 changes: 1 addition & 1 deletion docs/css/basics/internal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ While **External Stylesheets** (our next topic) are the default standard, intern

### Interactive Internal Styles Demo

Use the live editor to change the styles and watch the change below. Notice how the single `h2` rule targets all `h2` elements.
Use the live editor to change the styles and watch the change below.

<CodePenEmbed
title="Interactive Internal Styles Demo"
Expand Down