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 Width, Height, min/max Limits, and box-sizing

CSS Tutorial / CSS Width, Height, min/max Limits, and box-sizing

Compare content-box and border-box sizing, percentage heights, fluid width limits, and the consequences of fixed heights for growing text.

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 Link States and Visible Keyboard Focus

CSS Tutorial / CSS Link States and Visible Keyboard Focus

Compare link states in a working multi-file example, inspect keyboard focus, and understand browser privacy restrictions on visited-link styles.

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.

CSS Tutorial / CSS position: relative, absolute, fixed, and sticky

CSS Tutorial / CSS position: relative, absolute, fixed, and sticky

Compare positioning modes in a complete example, identify containing blocks, and troubleshoot sticky limits and overlapping content.

CSS Tutorial / CSS Transforms and Transitions

CSS Tutorial / CSS Transforms and Transitions

Compare transform order and origins, add hover and keyboard transitions, and test overflow and reduced-motion behavior.

CSS Tutorial / CSS Background Colors and Images: cover and contain

CSS Tutorial / CSS Background Colors and Images: cover and contain

Create and load a local background image, compare repetition, cover, contain, and position, and diagnose image-path and cropping problems.

CSS Tutorial / Flexbox Alignment, Wrapping, gap, grow, and shrink

CSS Tutorial / Flexbox Alignment, Wrapping, gap, grow, and shrink

Compare Flexbox alignment and wrapping, distribute space with flex values, and prevent long content from blocking item shrinkage.

CSS Tutorial / CSS Paragraph and List Styling

CSS Tutorial / CSS Paragraph and List Styling

Style paragraphs and ordered or unordered lists, compare inside and outside markers, and check spacing and wrapped text on narrow screens.

CSS Tutorial / Build a Responsive Website with HTML and CSS

CSS Tutorial / Build a Responsive Website with HTML and CSS

Create a complete two-file learning website with responsive cards and navigation, then test long text, keyboard focus, zoom, and reduced motion.