AD JB Toolbox 01 EN

CSS Tutorial / CSS Inheritance, Specificity, and the Cascade

The cascade chooses between competing CSS declarations, while specificity compares the strength of selectors within the relevant cascade conditions. Inheritance supplies certain values from a parent when no applicable declaration determines them; these are related but different mechanisms.

Distinguish inheritance from direct declarations

Inheritance is when a child element inherits the value of its parent element. While text color and font-related properties are generally inherited, border and padding are not inherited by default. If you assume that all properties will be the same as their parent, you may end up finding unexpected borders in your paragraphs.

#main {
  color: purple;
  border: 1px solid purple;
}
p { color: #555; }
<main id="main">
  <h1>Small Garden</h1>
  <p>Visitor information.</p>
</main>

Assuming we only apply these two pieces, h1 will inherit the purple color from its parent main. The gray color you specify is applied to p. Just because the parent's #main is an ID selector, it does not trump the child p's direct assignment. This is because it is not a competition between two selectors applying to the same element. The border is created around main's box and is not duplicated by the borders of h1 and p respectively.

Non-inherited properties can also inherit the parent's calculated value by specifying it as border: inherit. Conversely, even if there is a declaration that applies to the element, even if it is an inherited property, that declaration is processed first. You can find out which properties are inherited and what inherit means in MDN's CSS inheritance description.

Follow the cascade decision process

Start with ordinary author CSS, such as the rules you write for this page. Before comparing declarations, verify that the selector matches, the syntax is valid, and conditions such as media queries apply. Exclude unmatched rules and invalid declarations from the comparison.

  1. Check the top conditions such as source, importance, and layer. Author CSS and user CSS/browser default style sources, whether !important, whether @layer is used, etc. are relevant here. If the top conditions are different, the decision is not made by comparing only the selector's scores.
  2. Compares selector specificity within the same conditions. Priority (specificity) is a criterion for comparing how specific a selector is. Compare ID, class family, and element family in that order.
  3. If the priority is the same, the declaration written later is used. In situations where there are no additional conditions such as @scope, as in the examples in this lesson, final ties are resolved in source order.
  4. For each property, CSS resolves the applicable declarations and then performs defaulting where necessary. Inheritable properties can obtain a parent value; other properties normally use their initial value. This does not mean that every declaration in a winning rule replaces an entire earlier rule.

The cascade is the complete CSS conflict-resolution process; selector specificity is one criterion within it. Animations, transitions, layers, and scopes introduce further rules, so the simple examples here do not represent every case. The W3C cascade sorting rules define the relationships between origin, importance, and layers. The full example below uses no animations, transitions, @layer, or @scope. The Organize CSS with Shared Styles, Nesting, and Layers demonstrates grouping rules into layers.

Compare specificity in three columns

The basic selector in this lesson can be read in three columns: number of IDs, number of classes/attributes/pseudo-classes, and number of elements/pseudo-elements. Compare from the left column, and if there is a difference, decide based on the result. Don't just memorize it as a decimal score table by simply adding ID=100, class=10, element=1. Just because there are a lot of classes doesn't mean it goes beyond the ID column.

selector ID Class, attribute, pseudo-class Element/Pseudo-element notation
p 0 0 1 0-0-1
.notice 0 1 0 0-1-0
p.notice 0 1 1 0-1-1
[required] 0 1 0 0-1-0
a:hover 0 1 1 0-1-1
p::before 0 0 2 0-0-2
#opening 1 0 0 1-0-0
#main .notice 1 1 0 1-1-0

p.notice and .notice have the same ID column and the same class column. There is a difference between 1 and 0 in the element column, so p.notice is high. #opening and p.notice have a difference of 1 and 0 in the first column, so #opening is high. Whitespace, relational notations such as >, +, ~ and the universal selector * do not directly increase the number of these comparisons.

p.notice { color: #087f5b; }
.notice { color: tomato; }

Under the same origin, importance, and layer conditions, p.notice has higher specificity than .notice, so its green color wins even when it appears earlier. Identical selectors have equal specificity, letting source order resolve a tie. Some functional pseudo-classes have additional specificity rules. See MDN: Specificity.

Resolve each property separately

.notice {
  color: blue;
  padding: 12px;
  border: 1px solid #087f5b;
}
.notice {
  color: tomato;
  padding: 20px;
}

If only these two rules are applied to the same element, color and padding use the declaration from the latter, and border from the previous rule remains. Just because there is no border in the following rule does not mean that the entire previous rule disappears. CSS should be understood as “determining values for each property” rather than “selecting an entire rule block”.

For example, the text color may come from an ID rule, the margin may come from a later class rule, and the border may come from a previous class rule. Even when you see the strikethrough in developer tools, read the declarations one by one. Just because the color has a strikethrough does not mean that the padding of the same block is not applied.

Predict the complete example before running it

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Small Garden</title>
  <style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
    #main { color: purple; }
    p { color: #555; }
    .notice {
      color: blue;
      padding: 12px;
      border: 1px solid #087f5b;
    }
    p.notice { color: #087f5b; }
    .notice { color: tomato; padding: 20px; }
    #opening { color: #1d4ed8; }
  </style>
</head>
<body>
<main id="main">
    <h1>Small Garden</h1>
    <p id="opening" class="notice">A: We open at 9am every day.</p>
    <p class="notice">B: Prepare a water bottle and comfortable shoes.</p>
    <p>C: Please inquire at the information desk.</p>
  </main>
</body>
</html>

Predict the colors of A·B·C and the notice margin before opening it in your browser. If you save the entire code as index.html and open it, you will get the following result. The body font and line height are auxiliary settings for easier viewing.

object and properties final result Reason for decision
color of h1 Purple Inherits the color of main. There are no other color declarations in h1.
color of A Blue #1d4ed8 #opening has higher specificity than p.notice, .notice, p applied to the same A.
color of B Green #087f5b p.notice has higher specificity than later .notices.
color of C Gray #555 It uses a direct value for p and does not inherit the parent's purple color.
padding of A·B 20px The two .notice declarations have the same specificity, so the latter padding wins.
border of A·B 1px green solid line Since there is no border declaration in the latter rule, the preceding valid declaration remains.

When checked in Computed, the color of A can be displayed as rgb(29, 78, 216), the color of B can be displayed as rgb(8, 127, 91), and the color of C can be displayed as rgb(85, 85, 85). Even if the color notation is different, it indicates the same value. Check that the padding is 20px in each direction and that the border thickness and line shape are the same.

Compare !important and inline styles

!important is a notation that changes the importance of a declaration. It's not a function that adds a large number to the three columns of the selector. From the same author's source, important declarations take precedence over regular declarations, so adding the rule below to the end of the entire example will change the color of both A and B to tomato. The plain color declaration in ID also does not take precedence over this important declaration.

.notice { color: tomato !important; }

This result does not mean that important is always stronger than all styles. User important styles, values during transitions, etc. follow a separate order. Even among important declarations, you must first check the source and layer. In this exercise, observe important and then delete the rule you added. Usually, it is better for maintenance to organize the selection range and structure first.

<p class="notice" style="color: purple;">B: Information on what to prepare</p>

In the original example where the important rule was deleted, if you put an inline color in B as above, it will take precedence over the regular style sheet rules and B will become purple. Inline styles are treated separately from the three default selector columns in the table above. Again, putting important in the general class rule allows it to take precedence over the regular color inline. Therefore, “if it is inline, it is unconditionally the strongest” is also an explanation without conditions.

Practice diagnosing conflicts

  1. In the original full example, move the p.notice rule to the bottom. Make sure B is still green and A retains the blue color of its ID. In states with high specificity, they will not be overturned simply by changing their order.
  2. Next, change only the p.notice selector to .notice and place it at the bottom. The color of B uses the green specified by the last .notice. Since we have the same selector, order is now the decision criterion. After confirmation, restore the original.
  3. It only removes id="opening" from A. See if A becomes the same green as B. Even though the ID of the parent main remains the same, it does not beat the green color assigned directly to A. After confirmation, your ID will be restored.
  4. In separate steps, apply the above important and inline examples one by one and compare them. Instead of leaving the previous practice rules behind, go back to the original and add the following conditions:

If the result differs from your expectation, Inspect CSS with DevTools: Styles and Computed. Select the correct element, find declarations for the property, compare their importance, selectors, and order, and then inspect the final value. Adding IDs or !important without finding the cause may change the color now while making later edits harder.

More in This Category
CSS Tutorial / CSS display: Block, Inline, inline-block, and Hiding

CSS Tutorial / CSS display: Block, Inline, inline-block, and Hiding

Compare block and inline sizing, replaced elements such as images, and the layout and interaction differences between common hiding techniques.

CSS Tutorial / Check Responsive CSS with Width, Zoom, and Keyboard Tests

CSS Tutorial / Check Responsive CSS with Width, Zoom, and Keyboard Tests

Follow a repeatable browser checklist, test breakpoint boundaries and longer text, and record layout problems before changing CSS rules.

CSS Tutorial / CSS Inheritance, Specificity, and the Cascade

CSS Tutorial / CSS Inheritance, Specificity, and the Cascade

Work through inheritance and conflicting rules, compare specificity and source order, and understand the limits of !important in a simplified example.

CSS Tutorial / CSS Overflow, Long Text Wrapping, and Ellipsis

CSS Tutorial / CSS Overflow, Long Text Wrapping, and Ellipsis

Compare scrolling, clipping, long-word wrapping, and single-line ellipsis, including keyboard access and minimum-size issues in layout containers.

CSS Tutorial / What CSS Does and How It Differs from HTML

CSS Tutorial / What CSS Does and How It Differs from HTML

Learn the roles of HTML and CSS through a complete page example, and see how styling changes presentation without replacing meaningful HTML.

CSS Tutorial / Fluid CSS Layouts with min, max, and clamp

CSS Tutorial / Fluid CSS Layouts with min, max, and clamp

Build a bounded fluid layout, compare flexible sizes and spacing, and check that longer content fits without introducing horizontal page scrolling.

CSS Tutorial / CSS Form States: Focus, Validation, disabled, and readonly

CSS Tutorial / CSS Form States: Focus, Validation, disabled, and readonly

Compare form states, create accessible labels and error messages, and inspect which enabled, disabled, and read-only fields enter submitted form data.

CSS Tutorial / CSS Keyframe Animations, Fill Modes, and Pausing

CSS Tutorial / CSS Keyframe Animations, Fill Modes, and Pausing

Build a complete animation example, compare end states and delays, pause decorative motion, and check a prefers-reduced-motion alternative.

CSS Tutorial / CSS Container Queries for Reusable Components

CSS Tutorial / CSS Container Queries for Reusable Components

Reuse one card in main content and sidebar containers, compare nearest and named containers, and verify the baseline layout when a query does not apply.

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

Measure the four box areas, compare padding shorthand and vertical margin collapse, and inspect the resulting dimensions in DevTools.