Have you ever wondered why, when you set a font colour on a big container, all the text inside it automatically picks up that same colour · even though you never said anything about colour for the smaller elements inside?
That is CSS inheritance at work.
In this lesson, you will learn exactly what inheritance is, why it exists, which CSS properties are inherited by default, which are not, and how you can take full control using the special keyword values inherit, initial, unset, and revert. By the end, you will build a mini-project · a styled blog-post card · that demonstrates everything in action.
No prior knowledge of inheritance is needed. If you know basic HTML structure (parent and child elements) and can write simple CSS rules, you are ready.
Before diving into inheritance, make sure you are comfortable with these ideas. If anything here is new, read it carefully · you will need it throughout the lesson.
What is a Parent Element and a Child Element?
In HTML, elements are nested inside each other. The outer element is the parent. The element inside it is the child.
<div> <!-- parent -->
<p>Hello</p> <!-- child of div -->
</div>Think of a folder on your computer. The folder is the parent. The files inside are the children.
What is a CSS Property?
A CSS property is a style instruction, like color, font-size, border, or background-color. You write it in a CSS rule like this:
selector {
property: value;
}For example:
p {
color: red;
}This sets the text colour of every <p> element to red.
What is the Document Tree (DOM)?
The HTML page is organised as a tree. The <html> element is the root. Inside it is <body>. Inside <body> are your headings, paragraphs, divs, and so on. Each element can have children, and each child can have its own children.
html
└── body
├── h1
└── div
├── p
│ └── span
└── ul
├── li
└── liUnderstanding this tree is the key to understanding inheritance, because styles travel down the tree from parent to child.
The Big Idea
CSS inheritance is the mechanism by which some CSS property values set on a parent element are automatically passed down to child elements · unless the child has its own rule that overrides it.
Imagine a family. A parent has blue eyes. Their child might inherit those blue eyes automatically without any extra effort. But if the child has brown eyes, that overrides the inherited trait.
CSS works the same way.
Why Does Inheritance Exist?
Inheritance exists to save you from writing the same styles over and over again. Without it, you would have to manually write font-family: Arial on every single element on your page · every heading, paragraph, list item, span, and button. That would be incredibly tedious.
With inheritance, you write it once on a parent, and all the children automatically pick it up.
Real-world analogy: Think of a company-wide memo that says "All employee emails must use Arial font, size 12." Every employee follows this rule without needing their own individual memo · unless a specific team has their own overriding instruction.
How Does It Work? The Three-Step Process
When the browser needs to decide what value a CSS property has on an element, it follows this logic:
Step 1 · Does the element have its own rule? If yes, use that value.
Step 2 · Is the property inherited? If the element has no rule, and the property is an inherited property, the browser looks at the element's parent. If the parent has a value, the child uses that value.
Step 3 · Use the initial value. If the property is not inherited and the element has no rule, the browser uses the property's default "initial" value (defined in the CSS specification).
Not every CSS property is inherited. The CSS language decides which ones are.
Properties That ARE Inherited by Default
These are mostly text-related properties. It makes sense · if you set a font for a section, you want everything inside that section to use the same font.
Here are the most common inherited properties:
colorfont-familyfont-sizefont-style(normal, italic)font-weight(normal, bold)font-variantfont(shorthand)letter-spacingline-heighttext-aligntext-indenttext-transformvisibilityword-spacinglist-style(and its sub-properties)cursor
Memory tip: If it affects how text looks or behaves, it is probably inherited.
Properties That Are NOT Inherited by Default
These are mostly layout and box properties. It would cause chaos if every child automatically had the same border or margin as its parent.
Here are common non-inherited properties:
bordermarginpaddingbackground-colorbackground-imagewidthheightpositiondisplayfloatoverflowbox-shadowopacity(special · see note below)
Note on
opacity:opacityis technically not inherited, but it visually affects children because children are painted inside the parent. If a parent hasopacity: 0.5, the children will appear at 50% opacity too · even though they did not inherit theopacityproperty. This is different from true inheritance.
Example 1 · color Is Inherited
<!DOCTYPE html>
<html>
<head>
<style>
div {
color: blue;
}
</style>
</head>
<body>
<div>
<p>This paragraph is inside the div.</p>
<span>This span is also inside the div.</span>
</div>
</body>
</html>What happens?
The <div> is set to color: blue. The <p> and <span> are children of the <div>. They have no color rule of their own. Because color is an inherited property, they inherit the blue colour from the <div>.
Expected output in the browser:
- "This paragraph is inside the div." · displayed in blue
- "This span is also inside the div." · displayed in blue
Ask yourself: What would happen if you added
color: reddirectly to the<p>? The<p>would show red, because its own rule overrides the inherited blue. Try it!
Example 2 · border Is NOT Inherited
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 2px solid black;
}
</style>
</head>
<body>
<div>
<p>This paragraph is inside the div.</p>
</div>
</body>
</html>What happens?
The <div> has a black border. The <p> inside it has no border rule. Because border is not an inherited property, the <p> does not get a border.
Expected output in the browser:
- The
<div>has a black border around it. - The
<p>inside has no border.
Ask yourself: Why is this a good thing? Imagine if every
<span>and<p>automatically got the same border as its parent container · pages would look cluttered and uncontrollable!
Example 3 · Inheritance Travels Multiple Levels
Inheritance passes down the entire family tree, not just one level.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Georgia, serif;
font-size: 18px;
color: #333;
}
</style>
</head>
<body>
<div>
<p>This is a paragraph. <span>This is a span inside the paragraph.</span></p>
</div>
</body>
</html>The family tree here: body → div → p → span
What happens?
The body has font-family: Georgia, font-size: 18px, and color: #333. None of the child elements (div, p, span) have their own font or colour rules. They all inherit from body.
Expected output in the browser:
- All text on the page appears in Georgia font, 18px, dark grey colour.
- This includes the text in
<p>and the nested<span>.
Real-world use: Web developers almost always set a base
font-family,font-size, andcoloronbodyor a root element, and let all children inherit those values. This creates consistent typography with minimal code.
CSS gives you four powerful keywords that let you take control of what value an element uses. You can use these as the value for any property.
Keyword 1: inherit
What it does: Forces the element to use the inherited value from its parent, even for properties that are not normally inherited.
When to use it: When a property is not inherited by default (like border or background-color), but you want a child to copy its parent's value.
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 3px dashed purple;
}
p {
border: inherit; /* Force the p to inherit the border from div */
}
</style>
</head>
<body>
<div>
<p>This paragraph inherits the border from its parent div.</p>
</div>
</body>
</html>Expected output:
- The
<div>has a 3px dashed purple border. - The
<p>inside also has a 3px dashed purple border (because ofborder: inherit).
Think about it: Without
border: inherit, the<p>would have no border. The keyword forces it to copy the parent's value.
Keyword 2: initial
What it does: Resets the property to its original default value as defined by the CSS specification · ignoring anything inherited from a parent.
When to use it: When you want to remove an inherited or explicitly-set value and go back to square one.
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: red;
}
p {
color: initial; /* Reset color back to the CSS default (black) */
}
</style>
</head>
<body>
<p>This paragraph's color is reset to the initial value.</p>
<span>This span still inherits red from body.</span>
</body>
</html>Expected output:
- The
<span>text appears in red (inherited frombody). - The
<p>text appears in the browser's default colour, which is black (reset to initial).
Important:
initialdoes not mean "the browser's default style". It means "the CSS specification's initial value for this property". Forcolor, the CSS initial value isCanvasText(which renders as black in most browsers). Fordisplay, the initial value isinline, notblock· which can surprise you if you usedisplay: initialon a<div>.
Keyword 3: unset
What it does: Works like a smart combination of inherit and initial:
- If the property is naturally inherited,
unsetacts likeinherit. - If the property is naturally not inherited,
unsetacts likeinitial.
When to use it: When you want to completely remove your custom styling and let the property fall back to its natural behaviour · without having to know whether it is inherited or not.
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: navy;
}
div {
color: green;
border: 2px solid orange;
}
p {
color: unset; /* color IS inherited, so acts like inherit → uses navy from body */
border: unset; /* border is NOT inherited, so acts like initial → no border */
}
</style>
</head>
<body>
<div>
<p>This paragraph uses unset for both color and border.</p>
</div>
</body>
</html>Expected output:
- The
<div>has green text and an orange border. - The
<p>has navy text (unset on an inherited property → inherits frombody, skipping thediv's green). - The
<p>has no border (unset on a non-inherited property → initial = no border).
Why is this useful?
unsetis particularly powerful in CSS resets and when overriding third-party CSS. You can useall: unsetto wipe all styles from an element at once.
Keyword 4: revert
What it does: Reverts the property value to the browser's default stylesheet value (what the browser would normally apply without any author CSS).
The difference from initial: initial goes back to the CSS specification default. revert goes back to what the browser itself would apply (the user-agent stylesheet). For most elements, this is very similar, but for elements like <h1> and <p>, the browser has its own default sizes and margins that initial would remove but revert would restore.
<!DOCTYPE html>
<html>
<head>
<style>
h1 {
font-size: 14px; /* We made h1 tiny */
font-weight: normal;
}
h1.restore {
font-size: revert; /* Go back to browser's default for h1 (usually ~2em or 32px) */
font-weight: revert; /* Go back to browser's default (bold) */
}
</style>
</head>
<body>
<h1>This h1 is styled tiny and non-bold.</h1>
<h1 class="restore">This h1 is reverted to browser defaults.</h1>
</body>
</html>Expected output:
- First
<h1>: tiny text, not bold. - Second
<h1>: large and bold · back to how the browser would normally render it.
Quick Summary Table of the Four Keywords
| Keyword | What it Does | Use Case |
|---|---|---|
inherit | Forces the element to use its parent's computed value | Make non-inherited properties behave as inherited |
initial | Resets to CSS specification default value | Strip all custom styling back to spec default |
unset | inherit if the property is inherited, initial if not | Smart reset that respects natural inheritance |
revert | Reverts to browser (user-agent) stylesheet default | Undo your custom styles, keep browser defaults |
CSS provides a special shorthand property called all that lets you apply one of the four keywords to every single CSS property of an element at once.
What is all?
all is a CSS property that represents every other CSS property (except unicode-bidi and direction). You can only give it one of the four values: inherit, initial, unset, or revert.
Example: all: unset
This is commonly used to create a completely unstyled element · useful for custom components where you want to start fresh.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial;
color: darkred;
font-size: 20px;
}
button {
all: unset; /* Strip every browser and inherited style from the button */
cursor: pointer;
}
</style>
</head>
<body>
<p>This text inherits font and color from body.</p>
<button>This button has all styles unset.</button>
</body>
</html>Expected output:
- The
<p>appears in Arial, darkred, 20px. - The
<button>has no browser default button styling (no border, no background, no padding) because all styles are unset. It displays as plain text.
Real-world use:
all: unsetis widely used in UI component libraries when building custom buttons, inputs, and interactive elements where you want zero inherited or browser-default styling as your starting point.
all Shorthand Property. Open your editor, type the examples above by hand, modify them, and observe what changes.Work through each exercise carefully. Read the objective, write the code, check your output.
Exercise 1 · Warm-Up: Let Inheritance Do the Work
Objective: Understand that a single style on a parent can style all its children automatically.
Scenario: You are building a blog post. You want all text inside the article to use a comfortable reading font and a soft dark colour.
Instructions:
- Create an HTML file with an
<article>element. - Inside the article, put an
<h2>, two<p>elements, and a<ul>with three<li>elements. - Write a CSS rule that sets
font-family: Georgia, serif,font-size: 17px, andcolor: #444only on thearticleelement. - Open the file in a browser and observe.
Expected output: All text inside the article · the heading, paragraphs, and list items · should appear in Georgia font, 17px, dark grey colour. You wrote the style only once.
Self-check questions:
- Did the
<li>elements also get the Georgia font, even though you didn't style them directly? - What would happen if you added
color: crimsonto just the<h2>?
Hint: Think about which element is the parent and which are the children.
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
article {
font-family: Georgia, serif;
font-size: 17px;
color: #444;
}
</style>
</head>
<body>
<article>
<h2>The Power of Inheritance</h2>
<p>CSS inheritance lets you write less code and maintain consistency.</p>
<p>Once you understand it, styling pages becomes much faster.</p>
<ul>
<li>Reduces repetition</li>
<li>Creates consistent design</li>
<li>Easy to override when needed</li>
</ul>
</article>
</body>
</html>Expected output: All text inside <article> appears in Georgia, 17px, #444 · including the <li> items and the <h2>.
Exercise 2 · Overriding Inheritance
Objective: Understand that a child's own rule overrides what it would inherit from a parent.
Scenario: You have a section with a default text colour, but one paragraph should stand out in a different colour.
Instructions:
- Create a
<section>withcolor: steelblue. - Inside the section, add three
<p>elements. - Give the second
<p>a class ofhighlightand setcolor: darkorangeon it. - Observe which paragraphs are blue and which is orange.
Expected output:
- Paragraph 1: steel blue (inherited)
- Paragraph 2: dark orange (own rule overrides inheritance)
- Paragraph 3: steel blue (inherited)
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
section {
color: steelblue;
}
.highlight {
color: darkorange;
}
</style>
</head>
<body>
<section>
<p>Paragraph one — inherited blue.</p>
<p class="highlight">Paragraph two — own rule: orange.</p>
<p>Paragraph three — inherited blue again.</p>
</section>
</body>
</html>Thinking prompt: What happens if you remove the
.highlightrule? All three paragraphs become blue. What if you also setcolor: inheriton.highlightexplicitly?
Exercise 3 · Using inherit to Force Non-Inherited Properties
Objective: Practice using the inherit keyword on a property that is not naturally inherited.
Scenario: You want all direct links inside a navigation bar to match the nav bar's text colour, even though color on <a> tags is overridden by the browser's default link styling.
Background to know: By default, browser stylesheets make <a> tags blue and underlined. When you set color on a parent, links inside it will not automatically pick up that colour · because the browser's default style for <a> overrides inheritance.
Instructions:
- Create a
<nav>element withcolor: whiteandbackground-color: #222. - Inside the nav, add three
<a>links. - First, check what the links look like without any
<a>styling (they will be blue · browser default wins). - Then add
color: inheritto your<a>selector. - Observe the difference.
Expected output:
- Without
color: inherit: links appear blue (browser default). - With
color: inherit: links appear white (inherited from the<nav>).
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
nav {
background-color: #222;
color: white;
padding: 10px;
}
nav a {
color: inherit; /* Force link to inherit white from nav */
margin-right: 20px;
text-decoration: none;
}
</style>
</head>
<body>
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
</body>
</html>Expected output: All three links appear in white text on a dark background, matching the nav's colour.
Exercise 4 · Using initial to Reset a Property
Objective: Practice using initial to completely strip an inherited value.
Scenario: Your entire page uses dark green text. You have a warning box that must use the browser's default text colour (black), regardless of what is inherited.
Instructions:
- Set
color: darkgreenon<body>. - Create a
<div class="warning">with a yellow background. - Inside the warning, add a
<p>. - Use
color: initialon the.warningclass. - Observe the result.
Expected output:
- All other text on the page: dark green (inherited from body)
- Text inside
.warning: black (reset to CSS initial value forcolor)
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: darkgreen;
font-size: 16px;
}
.warning {
background-color: #fffacd;
border: 1px solid #f0c040;
padding: 10px;
color: initial; /* Reset to CSS default: black */
}
</style>
</head>
<body>
<p>This text inherits dark green from body.</p>
<div class="warning">
<p>Warning: this text is reset to the initial color (black).</p>
</div>
<p>Back to dark green again.</p>
</body>
</html>Exercise 5 · Using unset in Practice
Objective: See how unset adapts to whether a property is inherited or not.
Instructions:
- Set
color: purpleon<body>. - Create a
<div>withcolor: tealandborder: 3px solid red. - Inside the
<div>, add a<p>withcolor: unsetandborder: unset. - Observe what the paragraph's colour and border end up being.
Expected output:
- The
<p>colour: purple (unset oncolor→ acts like inherit → skips div's teal → gets body's purple) - The
<p>border: none (unset onborder→ acts like initial → initial value of border is none)
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: purple;
}
div {
color: teal;
border: 3px solid red;
}
p {
color: unset; /* Inherited property → behaves like inherit → gets purple from body */
border: unset; /* Non-inherited property → behaves like initial → no border */
}
</style>
</head>
<body>
<div>
<p>What color am I? What border do I have?</p>
</div>
</body>
</html>Challenge: Change
color: unsettocolor: inherit. Does the result change? (Yes ·inheritwould grab teal from the immediate parent<div>, not purple from<body>.unsetgoes to the natural inherited value which follows the full cascade.)
These are the mistakes that beginners almost always make when learning CSS inheritance. Study them carefully so you can avoid them.
Mistake 1 · Assuming ALL Properties Are Inherited
Wrong thinking: "I set border: 2px solid black on my <div>, so all the <p> elements inside should also have that border."
What actually happens: border is not inherited. Child elements will have no border.
Fix: If you want children to have the same border, you must either write a CSS rule targeting them directly, or use border: inherit on the children.
/* Wrong assumption — border does NOT automatically pass to children */
div {
border: 2px solid black;
}
/* Fix option 1: Target children directly */
div p {
border: 2px solid black;
}
/* Fix option 2: Force inheritance */
div p {
border: inherit;
}Mistake 2 · Confusing initial with "Browser Default"
Wrong thinking: "initial gives me the browser's default style for this element."
What actually happens: initial gives you the CSS specification's initial value, not the browser's. For font-size, the CSS initial value is medium (not the browser's 16px rendering of it). For display, initial is inline · so display: initial on a <div> makes it inline, which might surprise you.
Fix: If you want the browser's default styling for an element, use revert, not initial.
/* Wrong: This makes the h1 display inline (CSS spec initial for display) */
h1 {
display: initial;
}
/* Correct: This restores the browser's default display for h1 (block) */
h1 {
display: revert;
}Mistake 3 · Forgetting That <a> Tags Override Colour Inheritance
Wrong thinking: "I set color: white on my navigation. All text inside, including links, will be white."
What actually happens: The browser's built-in stylesheet sets <a> colour to blue (or purple for visited). This overrides the inherited colour. You must explicitly set color: inherit (or a specific colour) on <a> elements.
/* Wrong — links will still be blue despite the parent having white */
nav {
color: white;
}
/* Correct — explicitly force links to use the parent's colour */
nav a {
color: inherit;
}Mistake 4 · Using all: unset and Losing Important Behaviour
Wrong thinking: "I'll use all: unset on my button to strip all styles."
What actually happens: all: unset removes everything · including cursor: pointer, display, and focus outlines. Your element may become inaccessible or behave unexpectedly.
Fix: After all: unset, add back the essential properties you need:
button {
all: unset;
cursor: pointer; /* Restore pointer cursor */
display: inline-block; /* Restore sensible display */
}
button:focus {
outline: 2px solid blue; /* Restore focus indicator for accessibility */
}Mistake 5 · Expecting Inheritance Across Unrelated Elements
Wrong thinking: "My <h1> has red text. My <p> should also get red text from it."
What actually happens: Inheritance only travels down the document tree · from parent to child. Sibling elements (elements at the same level) do not inherit from each other. A <p> after an <h1> is not the <h1>'s child; they are siblings. Only a common ancestor can pass styles to both.
<!-- Wrong: thinking h1's color passes to p (they are siblings, not parent/child) -->
<h1 style="color: red;">Title</h1>
<p>Does this get red? NO — it is a sibling, not a child.</p>
<!-- Correct: wrap them in a parent and set color on the parent -->
<div style="color: red;">
<h1>Title</h1> <!-- inherits red -->
<p>Paragraph</p> <!-- inherits red -->
</div>In this project, you will build a blog post card that uses CSS inheritance cleverly. You will set styles on parent elements and let children inherit them · then override only where needed. You will also use inherit and initial in context.
Project Goal
Create a blog post card that looks like a simple article preview · with a heading, author name, paragraph text, a tag list, and a "Read More" link · all styled primarily through inheritance from a parent container.
Stage 1 · HTML Setup
Objective: Build the HTML structure first.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog Post Card</title>
<link rel="stylesheet" href="card.css">
</head>
<body>
<div class="card">
<h2 class="card-title">Understanding CSS Inheritance</h2>
<p class="card-author">By Alex Johnson • April 2026</p>
<p class="card-excerpt">
CSS inheritance is one of the most powerful but misunderstood features of
the language. Once you master it, you will write far less CSS and maintain
your stylesheets much more easily.
</p>
<ul class="card-tags">
<li>CSS</li>
<li>Web Design</li>
<li>Beginner</li>
</ul>
<a href="#" class="card-link">Read More →</a>
</div>
</body>
</html>