Learning path · Level 2 · Tutorial 2

Resolve CSS Conflicts with the Cascade

Explain why a CSS declaration wins and correct unexpected styling using the cascade, specificity, and inheritance.

  • Level: Beginner
  • Duration: 13 min
  • 8 steps
Start tutorial Back to the path
Resolve CSS Conflicts with the Cascade

What you will go through

  1. See What the Cascade Decides See how the cascade selects a winning declaration for one property and why an author color can replace a browser-default link color without changing its underline. 2 min
  2. Compare Selector Specificity Compare selector specificity tuples for competing normal author stylesheet declarations. 2 min
  3. Use Source Order Only to Break a Tie Use source order as a tie-breaker between equal-specificity stylesheet rules, and recognize when a higher-specificity selector still wins. 1 min
  4. Place Inline Styles and !important Correctly Resolve author-style conflicts by separating normal inline precedence from declaration importance. 2 min
  5. Separate Inheritance from Direct Styling Determine whether a child’s color comes from its own declaration or from its parent, and use inherit intentionally. 2 min
  6. Trace the Winning Declaration in Developer Tools Use Developer Tools to locate the declaration responsible for an unexpected color, distinguish overridden and inherited entries, and confirm the computed value. 2 min
  7. Fix the Cause Instead of Escalating Repair a diagnosed CSS color conflict by changing its source-level cause instead of increasing selector specificity or importance. 1 min
  8. Resolve a Complete Styling Conflict Independently diagnose, repair, and verify a CSS color conflict in the local Project Update example. 2 min

What you will learn

  • Predict the winning declaration in common conflicts involving stylesheet rules, inline styles, and !important.
  • Compare selector specificity and apply source order only when earlier priorities are equal.
  • Distinguish inherited values from declarations that directly target an element.
  • Use computed styles and overridden declarations to locate and fix a styling conflict.

Before you start

  • Apply CSS with Stylesheets and Selectors

Step 1 of 8

See What the Cascade Decides

See how the cascade selects a winning declaration for one property and why an author color can replace a browser-default link color without changing its underline.

Follow the declaration, not the whole rule

One property at a time

The cascade chooses a winning declaration one property at a time. It does not declare an entire CSS rule a winner or loser.

For a given element and property, the browser considers only declarations that are valid, applicable, and matched by their selectors. A rule can therefore win for color while another property still comes from browser default styles.

A property-level cascade decision

Diagram showing declarations for a link's color passing through cascade decisions, resulting in a navy underlined link.

For one property, compare origin and importance first. If needed, compare selectors next; source order resolves a remaining tie. An inline declaration is a distinct consideration within author styles.

Tip

Scope for this tutorial

This tutorial uses ordinary unlayered CSS. It does not cover scoped rules, animations, or transitions. Those features can add further cascade considerations.

A normal author color replaces the default

Browser defaults versus author styles

Browser default styles come from the browser, also called the user-agent origin. Styles in styles.css are author styles.

A normal author declaration takes precedence over a normal browser-default declaration. That comparison decides only the property being considered. If no author declaration changes a link's text-decoration, its native underline can remain even when its color changes.

index.html

Save this as index.html. Keep it in the same folder as styles.css.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Project Update</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="notice">
    <h1>Project Update</h1>
    <p id="status" class="message is-alert">Review needed.</p>
    <p class="message">Next update tomorrow.</p>
    <a href="#status">Read the update</a>
  </main>
</body>
</html>

styles.css

Save this matching stylesheet as styles.css, then open or refresh index.html in your browser.

css
a {
  color: navy;
}
Expected output
Read the update is navy and remains underlined.

Expected browser result after both files are saved in the same folder and index.html is opened.

Read the result by property

The a rule matches the link and contains a valid color declaration. It is a normal author style, so it becomes the winning declaration for the link's color instead of the normal browser-default link color. The rule says nothing about text-decoration, so it does not remove the native underline.

Check your reasoning

Explain this cascade result

A browser's default styles give a link both a color and an underline. The following matching author rule is then loaded:

a {
  color: navy;
}

Write the link's final color. Then explain why its underline remains visible, using the ideas of browser default styles, author styles, and separate properties.

Write at least 80 characters (0/80).

Step 2 of 8

Compare Selector Specificity

Compare selector specificity tuples for competing normal author stylesheet declarations.

Count the parts that matter

Specificity is a three-part tuple

When two normal author stylesheet declarations set the same property on the status paragraph, compare their selector specificity. Write each selector as (IDs, classes/pseudo-classes, types).

Count an ID in the first column, a class or ordinary pseudo-class in the second, and a type selector in the third. Compare from left to right. A value in an earlier column always matters more than any number in a later column.

Read tuples from left to right

Diagram showing an ID-based selector, a class-based selector, and a type-based selector aiming at the same paragraph, with the ID column taking priority first.

Compare IDs first, then classes and pseudo-classes, then type selectors.

Count only selector parts

For example, #status is (1, 0, 0), while .notice > .message is (0, 2, 0). The first selector wins this comparison because 1 ID beats 0 IDs.

The > child combinator adds nothing. Neither does the universal selector *. A selector is not stronger merely because it looks longer or more deeply nested.

Apply the comparison

Tuple reference

These selectors are familiar from the Project Update page. :root is an ordinary pseudo-class, so it contributes to the middle column. The universal selector and the child combinator contribute zero.

Specificity tuples for individual selectors
SelectorIDsClasses/pseudo-classesTypesTuple
p001(0, 0, 1)
.message010(0, 1, 0)
.notice > .message020(0, 2, 0)
#status100(1, 0, 0)
:root010(0, 1, 0)
*000(0, 0, 0)

Predict the winning declaration

All three rules match the status paragraph. Because these are competing normal author stylesheet declarations, specificity decides this conflict.

css
p {
  color: black;
}

.notice > .message {
  color: navy;
}

#status {
  color: maroon;
}

Compare, do not add a score

The winning declaration is color: maroon; from #status, with (1, 0, 0). Even though .notice > .message has two class selectors, (0, 2, 0) cannot defeat a selector with one ID.

If competing declarations have equal tuples, specificity alone cannot decide; another cascade check is needed.

Practice counting specificity

Match selectors and tuples

Match each selector to its specificity tuple.

Tap an item and then its matching pair.

Use specificity to finish the conflict

Complete the winning declaration

Complete the declaration that produces the same status result established in the previous example.

css
p {
  color: navy;
}

.notice > .message {
  color: black;
}

#status {
  color: ;
}

Step 3 of 8

Use Source Order Only to Break a Tie

Use source order as a tie-breaker between equal-specificity stylesheet rules, and recognize when a higher-specificity selector still wins.

Break an equal-specificity tie

A later equal rule wins

Source order breaks only a tie

The status paragraph matches both class selectors below. .message and .is-alert each have specificity (0, 1, 0).

When earlier cascade priorities and specificity are equal, the declaration written later in source order becomes the winning declaration. Source order is only a tie-breaker: a later declaration does not automatically win every conflict.

Equal selectors, ordered rules

A diagram shows two equal-priority class rules in vertical stylesheet order; the lower maroon rule controls the status paragraph.

Both matching class selectors have (0, 1, 0), so the later .is-alert declaration wins for the status paragraph.

styles.css

In styles.css, place the alert rule after the shared message rule. With the shared index.html from this tutorial, save the file and refresh the page.

css
.message {
  color: navy;
}

.is-alert {
  color: maroon;
}
Expected output
Review needed. is maroon.
Next update tomorrow. is navy.

Expected rendered result after saving and refreshing the linked local page.

Read order from the stylesheet

Class order is not source order

The order of names in an HTML class attribute only lists the classes an element has. It does not establish CSS source order.

Therefore, class="message is-alert" and class="is-alert message" match the same two selectors. The positions of the rules in styles.css resolve their tie.

For ordinary linked stylesheets, the document order of stylesheet links also matters. It does not depend on which stylesheet file finishes downloading first.

Keep the locations separate

Use source order only after the competing declarations are otherwise tied.

Where source order is determined
LocationDoes it decide an equal-priority, equal-specificity tie?
Order of names in `class`No
Rule position in `styles.css`Yes
Position of stylesheet links in the documentYes
File download completionNo

Practice: create the tie-break

Create the tie-break

Arrange the two stylesheet rules to make the status paragraph maroon. The comparison paragraph should remain navy.

Your sentence

Available words

Final check: apply the rule and its limit

Tie-break or higher specificity?

Write a short two-part cascade check.

  1. Write two rules using .message and .is-alert, in the source order that makes the status paragraph maroon while the comparison paragraph remains navy. Include the two specificity tuples and explain the tie-break.
  1. In a separate conflict, add a later matching ID-selector rule for the status paragraph that gives it a different color. State which kind of declaration wins and why moving a class rule later cannot change that result.

Write at least 120 characters (0/120).

Step 4 of 8

Place Inline Styles and !important Correctly

Resolve author-style conflicts by separating normal inline precedence from declaration importance.

Recognize normal inline precedence

Normal inline versus stylesheet CSS

An inline declaration is written in an element’s style attribute. In ordinary unlayered author CSS, a normal inline declaration takes precedence over normal author stylesheet declarations that target the same property.

This is not a fourth part of a specificity tuple. First compare the applicable declarations’ priority; normal inline styling has its own precedence within author styles. The status paragraph therefore displays navy here, even though #status is an ID selector.

Project Update

index.html

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Project Update</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="notice">
    <h1>Project Update</h1>
    <p id="status" class="message is-alert" style="color: navy;">Review needed.</p>
    <p class="message">Next update tomorrow.</p>
    <a href="#status">Read the update</a>
  </main>
</body>
</html>

A competing normal author declaration

styles.css

css
#status {
  color: maroon;
}

Why navy displays

A diagram shows an active navy path from an inline attribute to the status paragraph and an overridden maroon path from a stylesheet rule.

The normal inline declaration is the winning declaration for color; the matching normal stylesheet declaration is overridden.

Put !important in the right comparison

Importance comes before inline precedence

!important belongs to one declaration, not to a selector or an entire rule. It changes that declaration’s importance category.

If the stylesheet declaration below replaces the normal declaration from the prior screen, it defeats the normal inline color: navy; declaration. The status paragraph becomes maroon.

Make only color important

styles.css

css
#status {
  color: maroon !important;
}

Three common outcomes

Within the ordinary author-style cases used here, compare importance before deciding between inline and stylesheet declarations. If both declarations are important, the inline declaration takes precedence. For two stylesheet declarations at equal importance, continue with specificity and then source order.

Compact guide for author-style conflicts involving the same `color` property.
ConflictWinning colorDeciding factor
Normal inline navy vs. normal stylesheet maroonnavyNormal inline precedence
Normal inline navy vs. important stylesheet maroonmaroonImportance category
Important inline navy vs. important stylesheet maroonnavyInline precedence at equal author importance

Warning

Important limitation

Do not treat !important as a universal override. Important user and browser declarations can outrank important author declarations. This tutorial focuses on the common author-style conflicts in ordinary unlayered CSS.

Check the meaning of !important

Quick check

Which statement accurately describes !important?

Apply the comparison order

Resolve all three conflicts

Match each author-style conflict on #status to its winning color and deciding factor. Assume ordinary unlayered CSS and no higher-origin important declaration.

Tap an item and then its matching pair.

Step 5 of 8

Separate Inheritance from Direct Styling

Determine whether a child’s color comes from its own declaration or from its parent, and use inherit intentionally.

Follow the color path

Where a child’s color comes from

Inheritance is a fallback path

The cascade first looks for declarations that determine color on the child itself. If the child has no such declaration, color can inherit the parent’s computed value.

So a parent declaration is not a competing candidate against a declaration that directly targets its child. It supplies a value only when the child needs one. color inherits, but not every CSS property does.

Parent value versus direct child value

Diagram showing that a child without its own color receives the parent’s navy color, while a child with a direct maroon color uses that value instead.

Inheritance supplies the parent’s computed color only when no winning declaration determines the child’s color.

Keep the parent and child comparisons separate

Direct styling and explicit inheritance

A selector on the parent may be more specific, and its declaration may be important, but it still targets the parent—not the paragraph. The p rule below directly targets each paragraph, so its color replaces inheritance.

Then #status directly targets the status paragraph. Its winning color: inherit; declaration intentionally asks for the parent’s computed color.

styles.css: direct color and inherit

These author styles apply to the shared Project Update structure.

css
main.notice {
  color: maroon !important;
}

p {
  color: navy;
}

#status {
  color: inherit;
}

Tip

Read the result in two stages

With all three rules present, the comparison paragraph uses its direct p color: navy. The status paragraph’s #status declaration wins among declarations targeting that paragraph, then inherit makes it use the parent’s computed maroon color.

Do not compare main.notice and p specificity to decide the paragraph’s direct color. They apply to different elements.

Apply the inheritance rule

Predict the status color

Consider these separate author-style cases for the status paragraph inside main.notice:

main.notice {
  color: maroon !important;
}
  1. There is no declaration targeting #status.
  2. This declaration is added:
#status {
  color: navy;
}
  1. Instead, this declaration is added:
#status {
  color: inherit;
}

Which complete prediction is correct?

Step 6 of 8

Trace the Winning Declaration in Developer Tools

Use Developer Tools to locate the declaration responsible for an unexpected color, distinguish overridden and inherited entries, and confirm the computed value.

Set up the conflict

Local diagnostic checkpoint

Use your existing local folder containing the Project Update files as a diagnostic checkpoint. Replace the contents of index.html and styles.css with the following files, then open or refresh index.html in your browser. This checkpoint intentionally gives the status paragraph several valid, matching color declarations to inspect.

index.html

Save as index.html in the same folder as styles.css.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Project Update</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="notice">
    <h1>Project Update</h1>
    <p id="status" class="message is-alert">Review needed.</p>
    <p class="message">Next update tomorrow.</p>
    <a href="#status">Read the update</a>
  </main>
</body>
</html>

styles.css

Save as styles.css, then refresh the browser page.

css
.notice {
  color: navy;
}

.message {
  color: black;
}

.is-alert {
  color: maroon;
}

#status {
  color: navy;
}
Expected output
Expected browser result:
- The status paragraph “Review needed.” appears navy.
- The comparison paragraph “Next update tomorrow.” appears black.

The heading can inherit navy from `.notice`. The link keeps its browser default styles because this stylesheet does not target it.

Trace the evidence

Read the matched rules

Inspect the actual Review needed. paragraph, not its parent. In Styles (Rules in Firefox), filter the matched rules for color.

A crossed-out declaration is an overridden declaration: it matches, but it is not the winning declaration. An entry under an inherited section comes from an ancestor. It supplies a value only when the selected element has no direct winning value for that property.

For these files, the direct #status rule is active. The .is-alert and .message color declarations are crossed out. The parent’s .notice color can appear in an inherited section, but it does not compete with declarations that directly target the paragraph.

How the panels separate evidence

Developer-tools diagram showing an active status rule, crossed-out competing rules, an inherited parent rule, and a computed RGB color traced to the active rule.

Inspect the selected paragraph first. The active direct declaration determines its computed color.

Tip

Confirm and test in Computed

Open Computed and filter for color. Browsers may normalize the named value navy to rgb(0, 0, 128). These are the same color, not a styling conflict. Expand or follow the property trace to confirm that the responsible rule is #status in styles.css.

To test your explanation, temporarily uncheck color: navy; in the #status rule. The status paragraph changes to maroon because the matching .is-alert declaration then wins. Re-check it afterward. This edit is diagnostic: it normally changes only Developer Tools, not your saved source file.

Check the panel labels

Identify the rule status

Match each developer-tool region to what it represents.

Tap an item and then its matching pair.

Report the result

Report your diagnostic evidence

Using your local checkpoint, inspect Review needed. and write one short diagnostic report:

  1. What color value appears in Computed?
  2. Which selector and file are responsible for it?
  3. What change do you observe after temporarily toggling that responsible declaration off?

Use the evidence from your own Developer Tools.

Write at least 80 characters (0/80).

Step 7 of 8

Fix the Cause Instead of Escalating

Repair a diagnosed CSS color conflict by changing its source-level cause instead of increasing selector specificity or importance.

Start from evidence, not escalation

Repair the responsible declaration

Begin a repair with evidence, not more cascade power. In the exact styles.css checkpoint from the previous step, Developer Tools identified #status { color: navy; } as the winning declaration for the status paragraph.

The intended result is:

  • The status paragraph is maroon.
  • The comparison paragraph remains black.

That evidence points to one obsolete, status-only rule. It does not point to a need for a stronger selector. Keep .message as the shared rule and .is-alert as the intended exception.

A targeted repair preserves the other paragraph

Diagram showing an obsolete direct navy status rule removed so a maroon alert rule affects only the status paragraph while the comparison paragraph keeps its black shared message rule.

Remove the cause of the conflict so the intended exception can win without changing the shared rule.

Smallest appropriate repairs

Use the responsible declaration as evidence before editing.

Repair the cause rather than creating a new contest.
Diagnosed causeSmallest repairAvoid
Wrong value in the winning ruleCorrect that valueAdding a stronger selector
Obsolete inline colorRemove the inline declarationAdding !important elsewhere
Unnecessary !importantRemove it when normal priority is enoughAdding another !important
Overly specific ruleSimplify or remove itMatching it with more IDs
Genuine equal-specificity tiePut the intended rule later in source orderChanging specificity when no tie exists

Warning

Avoid escalation

Do not add another ID selector or !important merely to defeat a declaration that should not exist. That creates a new specificity or importance contest and makes a later repair harder to understand. First correct, remove, simplify, or reorder the declaration that inspection identified as the cause.

Repair the exact local checkpoint

Continue with the exact diagnosed stylesheet

Current styles.css from the Step 6 diagnostic checkpoint

css
.notice {
  color: navy;
}

.message {
  color: black;
}

.is-alert {
  color: maroon;
}

#status {
  color: navy;
}
Expected output
Status paragraph color: navy
Comparison paragraph color: black

Expected visible colors after saving this unchanged checkpoint and refreshing the browser. The link is not part of this color checkpoint.

Delete the obsolete source rule

This is the same stylesheet used in the prior diagnostic checkpoint. The direct #status declaration has specificity (1, 0, 0), so it overrides .is-alert.

In your local styles.css, delete the entire #status rule. Save the source file and refresh the browser. Do not make this change only in Developer Tools.

Afterward, .message and .is-alert both match the status paragraph with (0, 1, 0). The later alert rule wins by source order. The comparison paragraph matches .message only, so it remains black. In Computed, these may appear as rgb(128, 0, 0) and rgb(0, 0, 0).

Practice the repaired stylesheet

Complete the targeted repair

After deleting the obsolete direct status rule in your local file, complete the repaired stylesheet.

css
.notice {
  color: navy;
}

.message {
  color: ;
}

.is-alert {
  color: ;
}

Verify and explain your repair

Justify the source-level repair

Make the targeted repair in your local source file, save it, refresh the page, and inspect both paragraphs in Styles (Rules in Firefox) and Computed. Write a short report that identifies the rule you removed, the active declaration for the status paragraph after the repair, and the computed color of each paragraph. Then explain why adding another ID selector or !important was unnecessary and why the comparison paragraph was preserved.

Write at least 120 characters (0/120).

Step 8 of 8

Resolve a Complete Styling Conflict

Independently diagnose, repair, and verify a CSS color conflict in the local Project Update example.

Set up and inspect the conflict

Challenge setup

Final challenge: repair Project Update

Use your local index.html and styles.css in the same folder. Replace their contents with the checkpoint below. Save both files and refresh the browser.

Before editing, inspect the result. Your repair target is:

  • Review needed. is maroon.
  • Next update tomorrow. is navy.
  • There is no inline color override and no !important declaration.

Predict the initial winning declaration before you change anything.

index.html

Replace the complete contents of index.html.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Project Update</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="notice">
    <h1>Project Update</h1>
    <p id="status" class="message is-alert" style="color: navy;">Review needed.</p>
    <p class="message">Next update tomorrow.</p>
    <a href="#status">Read the update</a>
  </main>
</body>
</html>

styles.css

Replace the complete contents of styles.css, then refresh index.html.

css
.notice {
  color: navy;
}

.is-alert {
  color: maroon;
}

.message {
  color: black;
}
Expected output
Review needed. is navy because of the inline declaration.
Next update tomorrow. is black because of the direct .message declaration.

This describes the visible initial browser result after both files are saved and the page is refreshed.

Read the initial state

Diagram of a parent with navy color, a status paragraph affected by inline and class declarations, and a comparison paragraph with its own direct color declaration.

The status paragraph has several applicable declarations. The comparison paragraph has a direct declaration, so it is not currently using the parent’s color.

Make a prediction

Predict the initial winner

Before you edit either file, which declaration is the initial winning declaration for the status paragraph?

Repair the cause in the source

Apply the smallest repair

Now repair the source files on your computer.

  1. In index.html, delete the stale inline style attribute from the status paragraph.
  2. In styles.css, put the shared .message rule before the alert rule, as in the exercise below.
  3. Complete the two declaration values so the comparison paragraph deliberately takes its parent’s computed color and the alert remains the exception.

Save both files after making the changes.

Complete the CSS repair

Complete the repaired stylesheet rules.

css
.notice {
  color: navy;
}

.message {
  color: ;
}

.is-alert {
  color: ;
}

Verify, explain, and finish

Verify with developer tools

Save your edits, refresh the page, and inspect each paragraph separately.

In developer tools, select the affected element. In Styles (Rules in Firefox), filter for color and identify the active declaration versus crossed-out overridden declarations. Then use Computed to confirm the final value. A named color can appear there in normalized rgb(...) form.

Developer-tool edits are useful tests, but make sure the source files contain your final repair.

Report your evidence

Write a short diagnostic report. Include:

  1. The initial winning declaration for the status paragraph.
  2. The final computed color for each paragraph, using either named values or normalized rgb(...) values.
  3. How inline precedence, equal-specificity source order, and inheritance account for the initial and final results.
  4. The declaration or source-file change you verified in Styles (Rules in Firefox) and Computed.

Write at least 180 characters (0/180).

Summary

Cascade repair recap

  • Compare applicable declarations in cascade priority order; use source order only after earlier priorities and specificity tie.
  • Treat inheritance separately: a direct declaration on a child can replace the parent’s inherited value.
  • Inspect the actual element in Styles (Rules in Firefox) and confirm the result in Computed.
  • Repair the responsible source declaration instead of escalating selectors or adding !important.

Tutorial complete

Congratulations! You completed: Resolve CSS Conflicts with the Cascade

You resolved a complete CSS conflict by tracing the winning declaration, repairing the source, and verifying the computed result.

Download the App now to have access to + 5000 free courses, exercises, certificates and lots of content without paying anything!

  • 100% free online courses from start to finish

    Thousands of online courses in video, ebooks and audiobooks.

  • More than 60 thousand free exercises

    To test your knowledge during online courses

  • Valid free Digital Certificate with QR Code

    Generated directly from your cell phone's photo gallery and sent to your email

Cursa app on the ebook screen, the video course screen and the course exercises screen, plus the course completion certificate