Why Your CSS Isn’t Working (And How to Fix It)
🤔 You Wrote the CSS. Nothing Changed.
You’ve carefully written a CSS rule. You save the file. You switch to the browser and hit refresh. And… nothing. The page looks exactly the same. No error message. No warning. Just silence.
This is one of the most frustrating experiences in web development — and it happens to everyone, from first-day beginners to senior engineers. CSS fails silently. When something is wrong, the browser doesn’t shout at you the way JavaScript does. It just quietly ignores the broken rule and moves on.
The good news? There are only a handful of reasons CSS doesn’t work, and once you know what they are, you can diagnose any problem in under a minute.
- Have you ever changed a CSS property and refreshed the page, only to see nothing happen?
- Do you know how to check whether your browser is actually loading your stylesheet?
- If two CSS rules target the same element, how does the browser decide which one wins?
In the next 30 minutes, you’ll learn the most common reasons CSS breaks — and build a systematic debugging checklist you can use every time something doesn’t look right.
Learning Objectives
By the end of this lesson, you'll be able to:
- ✓ Identify Identify the most common reasons CSS rules are ignored by the browser
- ✓ Diagnose CSS syntax errors including missing brackets, colons, and semicolons
- ✓ Explain Explain how specificity and the cascade determine which styles win
- ✓ Use browser DevTools to inspect, toggle, and edit CSS rules in real time
- ✓ Apply Apply a systematic debugging checklist to fix broken styles quickly
Why This Matters:
Professional developers spend a surprising amount of time debugging CSS. The difference between a beginner and an expert isn’t that experts never have CSS problems — it’s that they can find and fix them in seconds. This tutorial gives you the same mental checklist that experienced developers use, so you stop guessing and start diagnosing.
Is Your CSS Even Loading?
Before you blame your rules, make sure the browser is actually reading your stylesheet. This is the number one cause of “my CSS isn’t working” for beginners — and it’s the easiest to fix.
Check 1: Is the <link> tag in your HTML?
Your HTML file needs a <link> element in the <head> that points to your stylesheet:
<head>
<meta charset="UTF-8">
<title>My Page</title>
<link rel="stylesheet" href="css/style.css">
</head>If this line is missing, your CSS file exists but the browser has no idea it’s there. It’s like writing a letter and never posting it.
Check 2: Is the file path correct?
The href must match the actual location of your CSS file. If your stylesheet is in a css/ folder, the path needs to include that folder:
Correct
<!-- File is at css/style.css -->
<link rel="stylesheet"
href="css/style.css">
<!-- File is in the same folder -->
<link rel="stylesheet"
href="style.css">Wrong
<!-- File is at css/style.css
but path says root -->
<link rel="stylesheet"
href="style.css">
<!-- Typo in folder name -->
<link rel="stylesheet"
href="CSS/styles.css">Case matters on servers
style.css and Style.css are the same file on your Mac — but on a Linux web server, they’re two different files. Always use lowercase filenames.
Check 3: Browser cache
Browsers cache (save a copy of) your CSS to load pages faster. When you edit your stylesheet and refresh, you might be seeing the old cached version.
Fix: Do a hard refresh:
- Mac: Cmd + Shift + R
- Windows/Linux: Ctrl + Shift + R
Or open DevTools (F12), go to the Network tab, and tick “Disable cache” while DevTools is open.
The browser takes a photocopy of your stylesheet and uses that instead of checking the original file every time. A hard refresh forces it to throw away the photocopy and look at the real file again.
Syntax Errors: The Silent Breakers
CSS doesn’t throw error messages like JavaScript. If you make a syntax mistake, the browser silently skips the broken rule — and sometimes everything that comes after it.
Missing curly brackets
If you forget a closing }, the browser can’t tell where your rule ends. Every rule below the missing bracket may also break.
Correct
h1 {
color: navy;
font-size: 2rem;
}
p {
line-height: 1.6;
}Broken
h1 {
color: navy;
font-size: 2rem;
/* Missing } above!
The p rule gets swallowed */
p {
line-height: 1.6;
}Missing colons and semicolons
Every CSS declaration needs a colon between the property and value, and a semicolon at the end:
/* ✅ Correct */
color: navy;
font-size: 2rem;
/* ❌ Missing colon */
color navy;
/* ❌ Missing semicolon */
color: navy
font-size: 2remA missing semicolon can cause the next property to be treated as part of the current value — the browser sees color: navy font-size: 2rem as one invalid value and ignores both.
Space between value and unit
This one catches people all the time:
/* ✅ Works */
font-size: 26px;
margin: 1.5rem;
/* ❌ Broken — space between number and unit */
font-size: 26 px;
margin: 1.5 rem;CSS requires the number and unit to be one continuous token. A space between them makes the value invalid, and the rule is silently ignored.
CSS was designed to be forward-compatible. When browsers encounter a property or value they don’t understand, they skip it instead of crashing. This means new CSS features can be added without breaking old browsers — but it also means your typos get silently ignored instead of flagged.
⏸️ ⏸️ Check: Loading & Syntax
Can you spot the problems?
- Your page has no styles at all. What is the very first thing you should check?
- You edited your CSS but the page still looks the same after refreshing. What could cause this?
- What happens when you forget a closing curly bracket } in CSS?
Check Your Answers
- Check that the <link> tag is in the <head> of your HTML and that the href path is correct. If the stylesheet isn’t linked, the browser has no idea it exists.
- Browser caching. The browser is showing you the old saved version of your stylesheet. Do a hard refresh (Cmd+Shift+R on Mac, Ctrl+Shift+R on Windows/Linux) to force it to re-download the file.
- The browser can’t tell where the rule ends, so it swallows everything that follows until it finds another closing bracket. This can break multiple rules below the mistake, not just the one with the error.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Selector Issues: Targeting the Wrong Thing
Your CSS might be perfectly valid, but if the selector doesn’t match any element in your HTML, the rule has nothing to style.
Typos in class and ID names
This is embarrassingly common — and hard to spot because CSS gives you no warning:
<!-- HTML -->
<div class="hero-banner">...</div>
/* CSS — typo! "heros" instead of "hero" */
.heros-banner {
background: navy;
}The selector .heros-banner matches nothing, so the rule is silently ignored. Always copy-paste class names from your HTML into your CSS to avoid this.
Forgetting the dot or hash
/* ❌ Targets an element called <hero-banner>
(which doesn't exist) */
hero-banner {
background: navy;
}
/* ✅ Targets class="hero-banner" */
.hero-banner {
background: navy;
}
/* ✅ Targets id="hero-banner" */
#hero-banner {
background: navy;
}Invalid selector lists
If you group selectors with commas and one of them is invalid, the entire rule is ignored in standard CSS:
/* ❌ :invalid-pseudo doesn't exist
— the ENTIRE rule is thrown out */
h1, h2, :invalid-pseudo {
color: navy;
}
/* ✅ Split them so a bad selector
doesn't break the good ones */
h1, h2 {
color: navy;
}Copy-paste is your friend
Instead of retyping class names, copy the class name from your HTML and paste it into your CSS. This eliminates typo-based selector mismatches instantly.
Specificity & the Cascade
This is where beginners get stuck the most. You write a rule, the selector is correct, the syntax is perfect — but the browser is applying a different rule instead. Why?
The cascade: last rule wins
When two rules have the same specificity and target the same element, the one that appears later in the stylesheet wins:
h1 {
color: red;
}
/* This one wins — it comes later */
h1 {
color: blue;
}Specificity: more specific rules win
But when rules have different specificity, the more specific one wins regardless of order. Think of specificity as a scoring system:
| Selector Type | Score | Example |
|---|---|---|
| Element | 1 point | p, h1, div |
| Class | 10 points | .hero, .nav-link |
| ID | 100 points | #header, #main |
| Inline style | 1000 points | style="color: red" |
/* Specificity: 1 (one element) */
p {
color: black;
}
/* Specificity: 10 (one class) — WINS */
.intro {
color: navy;
}
/* Specificity: 11 (one element + one class) */
p.intro {
color: red;
}A class selector (.intro) always beats a plain element selector (p), no matter which comes first in the file.
“Deliver this to any house on the street” (element selector) is vague. “Deliver to the blue house” (class) is more specific. “Deliver to 42 Smith Street” (ID) is exact. The more specific instruction always wins.
The !important trap
You might see advice to add !important to force a rule to win:
p {
color: red !important;
}This works — but it’s a trap. Once you start using !important, the only way to override that rule is with another !important, and soon your stylesheet becomes an unmanageable mess. Professional developers treat !important as a last resort, not a first fix.
Instead of !important:
- Make your selector more specific (add a class or parent selector)
- Move the rule later in the stylesheet
- Remove the conflicting rule that’s winning
⏸️ ⏸️ Check: Selectors & Specificity
Test your understanding:
- You wrote .hero { color: red; } but the text stays black. In DevTools, you see that p { color: black; } has a line through it and body { color: black; } does not. What’s happening?
- Which selector wins: p { color: red; } or .intro { color: blue; }?
- Why is !important considered bad practice?
Check Your Answers
- The colour is being inherited from body, not from a p rule. Since .hero doesn’t have a colour conflict with a higher-specificity rule, check that the selector actually matches — the class name might be misspelled in the HTML or CSS.
- .intro wins because a class selector (specificity ~10) always beats an element selector (specificity ~1), regardless of which comes first in the stylesheet.
- Because the only way to override an !important rule is with another !important rule that has equal or higher specificity. This creates an escalating war of !important declarations that makes your stylesheet very difficult to maintain.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Inheritance & Third-Party Conflicts
Some CSS properties are inherited — child elements automatically pick up the value from their parent. Others are not.
What inherits and what doesn’t
Inherited
colorfont-familyfont-sizeline-heighttext-align
Set these on a parent and children get them for free.
NOT inherited
backgroundbordermarginpaddingwidth/height
You must set these on each element individually.
Third-party CSS conflicts
If you’re using a CSS framework (Bootstrap, Bulma, Tailwind) or a CMS theme, their styles load alongside yours. When your rules don’t seem to take effect, the framework’s rules are probably winning the specificity battle.
/* Bulma's button styles might be:
.button { background-color: white; }
Specificity: 10
Your override needs at least the same specificity: */
.button.my-custom-button {
background-color: navy;
}
/* Specificity: 20 — wins! */Tip: In DevTools, look for rules with a line-through — that means they’re being overridden by a more specific rule. The winning rule is shown above it.
Browser DevTools: Your CSS Debugger
DevTools is the single most valuable tool for debugging CSS. Every browser has them built in — no installation required.
Opening DevTools
- All browsers: Press F12 or right-click any element → Inspect
- Mac shortcut: Cmd + Option + I
- Windows/Linux: Ctrl + Shift + I
The Elements panel
The Elements panel shows your HTML on the left and the CSS rules for the selected element on the right. This is where you’ll do most of your debugging.
Key debugging techniques
- Inspect the element — Right-click the problem element → Inspect. The Styles panel shows every CSS rule that applies.
- Look for crossed-out rules — A line through a property means it’s being overridden by another rule. Look above it to see what’s winning.
- Toggle rules on/off — Click the checkbox next to any property to disable it temporarily. This is the fastest way to find which rule is causing a problem.
- Edit values live — Click on any value (e.g.
navy) and type a new one. The page updates instantly. This lets you experiment without touching your file. - Check the Computed tab — This shows the final value the browser is actually using, after all cascade and inheritance calculations.
It lets you see inside the page — which rules are applied, which are overridden, and exactly why. If CSS is the clothes your page wears, DevTools lets you see the skeleton underneath.
The outline trick for layout debugging
If an element seems to be the wrong size or in the wrong place, try adding a temporary outline to everything:
/* Add this temporarily */
* {
outline: 1px solid red;
}This draws a red border around every element so you can see their boundaries. Unlike border, outline doesn’t affect the element’s size or layout, so it won’t change what you’re debugging.
⏸️ ⏸️ Check: DevTools
Make sure you know the essentials:
- How do you open DevTools in any browser?
- In the Styles panel, what does a line through a CSS property mean?
- Why is outline better than border for debugging layout issues?
Check Your Answers
- Press F12, or right-click any element and choose Inspect. On Mac you can also use Cmd+Option+I.
- It means that property is being overridden by another rule with higher specificity or that appears later in the cascade. The winning rule is shown above the crossed-out one.
- Unlike border, outline does not affect the element’s size or layout. Adding a border changes the element’s dimensions (unless you use box-sizing: border-box), which can shift the layout and change the very problem you’re trying to debug.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Layout Gotchas
Some CSS problems aren’t about individual properties — they’re about how elements interact with each other in the layout.
Overflow issues
If content is spilling outside its container or a horizontal scrollbar appears, check for:
- Fixed-width elements inside a flexible container
- Images wider than their parent (fix:
img { max-width: 100%; }) - Padding or borders adding to the element’s total width (fix:
box-sizing: border-box)
Collapsed margins
When two vertical margins touch, they don’t add up — the larger one wins. This is called margin collapsing and it catches everyone off guard:
/* You'd expect 40px of space between them.
You actually get 30px (the larger margin wins). */
h1 {
margin-bottom: 20px;
}
p {
margin-top: 30px;
}Z-index confusion
z-index only works on elements with a position value other than static. This is the most common reason z-index “doesn’t work”:
/* ❌ Won't work — no position set */
.popup {
z-index: 999;
}
/* ✅ Works — position is set */
.popup {
position: relative;
z-index: 999;
}Your CSS Debugging Checklist
When your CSS isn’t working, run through this checklist in order. Most problems are found in the first three steps:
The Checklist
- Is the stylesheet linked? — Check the
<link>tag in your HTML<head> - Is the file path correct? — Check for typos and wrong folder paths
- Is it cached? — Do a hard refresh (Cmd/Ctrl + Shift + R)
- Any syntax errors? — Check for missing
{},:, and; - Does the selector match? — Check class/ID spelling, dots, and hashes
- Is it being overridden? — Open DevTools and look for crossed-out rules
- Is specificity losing? — Make your selector more specific
- Is it inherited or not? — Check whether the property inherits
- Browser compatibility? — Check MDN for browser support
Guided Practice: Fix These Broken Styles
Download the starter files:
Save both files to a folder on your computer (keep the css/ subfolder structure).
Debug a Broken Stylesheet
You’ve been given a webpage with CSS that isn’t working. Use your debugging checklist to find and fix each issue.
Create the test page
Create a new file called debug-practice.html and add this HTML:
CSS Debug Practice
My Website
Welcome
This is a test page for debugging CSS.
💡 Need a hint?
Create the broken stylesheet
Create css/debug.css with these intentionally broken rules:
/* Bug 1: Missing closing bracket */
h1 {
color: navy;
font-size: 2.5rem;
/* Bug 2: Selector typo */
.hero_section {
background-color: #f0f0f0;
padding: 3rem;
}
/* Bug 3: Missing colon */
nav ul {
list-style none;
display: flex;
gap: 1.5rem;
}
/* Bug 4: Space in value */
.intro {
font-size: 1.2 rem;
line-height: 1.8;
}💡 Need a hint?
Open the page and observe
Open debug-practice.html in your browser. Notice what looks wrong:
- Is the h1 styled?
- Does the hero section have a background?
- Is the nav list horizontal?
- Is the intro paragraph larger?
Open DevTools (F12) and inspect the h1 element. What do you see in the Styles panel?
💡 Need a hint?
Fix Bug 1: Missing bracket
Add the missing } after the h1 rule. Save and hard-refresh. The h1 should now be navy and large — and the rules below it should start working.
h1 {
color: navy;
font-size: 2.5rem;
} /* ← This was missing! */💡 Need a hint?
Fix Bugs 2–4
Now fix the remaining three bugs:
- Bug 2: The HTML uses
class="hero-section"but the CSS says.hero_section(underscore vs hyphen). Change the CSS to.hero-section - Bug 3:
list-style noneis missing a colon. It should belist-style: none; - Bug 4:
1.2 remhas a space. Remove it to get1.2rem
💡 Need a hint?
Verify in DevTools
After all fixes, inspect each element and confirm:
- h1 — Styles panel shows
color: navyandfont-size: 2.5rem(no line-through) - .hero-section — Shows
background-color: #f0f0f0 - nav ul — Shows
display: flexandlist-style: none - .intro — Shows
font-size: 1.2rem
No rules should be crossed out or inactive.
💡 Need a hint?
You're on track if you can:
- ☐ All headings are styled with the correct colours
- ☐ The navigation links appear horizontally
- ☐ The hero section has its background colour
- ☐ No CSS rules are being silently ignored
- ☐ You can explain why each fix works
Independent Challenge: CSS Detective
Download the challenge files:
This page has 7 bugs hidden in the CSS. Save both files and use DevTools to find and fix them all.
💪 CSS Detective: Find All the Bugs
Now try this on your own without hints!
Your Task:
Requirements:
- Create an HTML page with at least a header, nav, hero section, and footer
- Write a CSS file with at least 7 intentional bugs (mix of categories from this tutorial)
- Include at least one missing-bracket error that breaks rules below it
- Include at least one selector typo (class name mismatch)
- Include at least one specificity conflict where the wrong rule wins
- Use DevTools to identify each bug before fixing it
- Document each bug you planted and how you fixed it in an HTML comment
Stretch Goals (Optional):
- Add a third-party CSS file (like a simple reset) and create a conflict that your custom styles need to override
- Use the browser Computed tab to trace an inherited property through three levels of nesting
- Create a z-index bug and fix it by adding the correct position property
Success Criteria:
| Criteria | You've succeeded if... |
|---|---|
| 7+ intentional bugs covering at least 3 categories | Meets expectations |
| Each bug is documented with the fix in a comment | Meets expectations |
| DevTools was used (not just guessing) to diagnose | Meets expectations |
| Stretch goals attempted — third-party conflict or z-index fix | Exceeds expectations |
| Clean, well-organised final stylesheet after all fixes | Exceeds expectations |
Summary
🏁 Lesson Complete: You Can Debug CSS
Key Takeaways:
- Always check the basics first: is the stylesheet linked, is the path correct, is the browser cached?
- CSS fails silently — a missing bracket, colon, or semicolon can break rules with no error message
- Specificity determines which rule wins: IDs beat classes, classes beat elements, and !important overrides all (but use it as a last resort)
- Browser DevTools let you inspect, toggle, and edit CSS rules in real time — learn to use them
- Most CSS problems fall into just a few categories: run through the debugging checklist and you’ll find the issue quickly
Learning Objectives Review:
Look back at what you set out to learn. Can you now:
- ✅ Identify the most common reasons CSS rules are ignored by the browser Check!
- ✅ Diagnose CSS syntax errors including missing brackets, colons, and semicolons Got it!
- ✅ Explain how specificity and the cascade determine which styles win Can explain it!
- ✅ Use browser DevTools to inspect, toggle, and edit CSS rules in real time Could teach this!
- ✅ Apply a systematic debugging checklist to fix broken styles quickly Check!
If you can confidently answer "yes" to most of these, you're ready to move on!
Think & Reflect:
💭 💭 Reflection Questions
- Which type of CSS bug have you encountered most often in your own projects?
- How will using DevTools change the way you debug styles compared to just editing the file and refreshing?
- Why do you think CSS was designed to fail silently instead of showing error messages?
- What is the first thing you will check next time your CSS doesn’t work?
🤔 Real-World Test:
Professional developers debug CSS every single day. The difference between a beginner and an expert isn’t that experts write perfect CSS — it’s that they can identify and fix problems in seconds using a systematic approach:
- Check the obvious (is the file loading?)
- Use DevTools to see what the browser is actually doing
- Fix one thing at a time and test after each change
Print out the debugging checklist from this tutorial and keep it next to your computer until it becomes second nature.
🎯 Looking Ahead:
Now that you can debug CSS, you’re ready to start writing more ambitious stylesheets. In the CSS Flexbox tutorial, you’ll learn modern layout techniques — and you’ll have the debugging skills to fix any problems along the way.
Recommended Next Steps
Practice Projects
Apply what you've learned with these hands-on projects:
Additional Resources
Deepen your understanding with these helpful resources:
- MDN: Debugging CSS - Mozilla's guide to diagnosing and fixing CSS problems.
- Chrome DevTools: CSS Reference - Official guide to inspecting and editing CSS in Chrome DevTools.