CSS Specificity & The Cascade
Learning Objectives: By the end of this lesson, you will be able to:
- Calculate CSS specificity values and predict which styles will be applied
- Understand how the cascade resolves conflicts between competing CSS rules
- Use specificity strategically to write maintainable CSS without relying on !important
- Debug specificity conflicts using browser developer tools and systematic approaches
1. Welcome and Introduction (5 minutes)
Icebreaker Activity
Welcome! Imagine you’re a judge in a courtroom where multiple CSS rules are arguing about who gets to style an element. Each rule has different levels of “evidence” - some have IDs (like official government documents), others have classes (like signed contracts), and some just have element selectors (like verbal agreements). If you could make one style always win over others, what would it be and why? Maybe you’d want your main brand color to always take precedence, or perhaps you’d ensure that accessibility styles can never be overridden?
Lesson Overview
- Duration: 90 minutes
- Prerequisites: Basic understanding of CSS selectors, properties, and HTML structure
- Materials Needed: Code editor, web browser with developer tools for inspecting specificity
2. Learning Objectives and Session Outline (5 minutes)
What We’ll Cover Today:
- Specificity Fundamentals - Understanding how browsers resolve competing CSS rules
- Specificity Calculation - Learning the point system and hierarchy of selector types
- The Cascade Mechanism - How source order, inheritance, and origins work together
- Practical Debugging - Using developer tools to diagnose and solve specificity conflicts
- Best Practices - Writing maintainable CSS that avoids specificity wars
Success Criteria:
By the end of this session, you should be able to look at any set of competing CSS rules and accurately predict which will be applied, debug specificity issues efficiently, and write CSS that leverages specificity strategically rather than fighting against it.
3. Foundation Knowledge (15-20 minutes)
Core Concepts
What is CSS Specificity?
CSS specificity is the algorithm that browsers use to determine which CSS rule should be applied when multiple rules could target the same element. Think of it as a scoring system where each type of selector has a different point value, and the rule with the highest total score wins.
Real-World Analogy: Specificity works like a hierarchy in an organization. An instruction from the CEO (ID selector) carries more weight than one from a department manager (class selector), which in turn outweighs a suggestion from a general employee (element selector). However, if the CEO isn’t available, the department manager’s instruction takes precedence.
Why This Matters: Understanding specificity is crucial because:
- Debugging: Most CSS bugs stem from specificity conflicts
- Maintainability: Proper specificity management keeps codebases organized
- Performance: Avoiding specificity wars prevents bloated CSS
- Predictability: Code behaves consistently when specificity is understood
The Cascade in CSS
The cascade is the fundamental algorithm that determines how CSS rules are applied. It considers four key factors in order:
- Source order: Later rules override earlier ones (when specificity is equal)
- Specificity: More specific selectors win over less specific ones
- Importance: Rules marked with !important override normal rules
- Origin: Author styles vs. user styles vs. browser defaults
How Browsers Process CSS
When a browser encounters an element, it follows this process:
- Collect all CSS rules that apply to the element
- Calculate specificity for each rule
- Apply rules in order of specificity (highest first)
- For equal specificity, use source order (last rule wins)
- Handle inheritance from parent elements
Key Terminology
- Specificity: The weight or priority assigned to a CSS selector
- Cascade: The algorithm that determines which CSS rules apply to elements
- Selector Weight: The numeric value calculated for specificity comparison
- Specificity Hierarchy: The ranking system for different selector types
- Source Order: The position of CSS rules in the stylesheet or document
- Inheritance: CSS properties that automatically pass from parent to child elements
4. Detailed Explanation and Examples (25-30 minutes)
Understanding Specificity Calculation
CSS specificity is calculated using a four-part scoring system, often represented as a,b,c,d:
The Specificity Scoring System
- a (Inline styles): 1000 points for style attributes in HTML
- b (IDs): 100 points for each ID selector (#myid)
- c (Classes, attributes, pseudo-classes): 10 points each (.class, [attr], :hover)
- d (Elements, pseudo-elements): 1 point each (div, ::before)
/* Examples of specificity calculations */
/* 0,0,0,1 = 1 point */
p { color: blue; }
/* 0,0,1,0 = 10 points */
.highlight { color: green; }
/* 0,0,1,1 = 11 points */
p.highlight { color: purple; }
/* 0,1,0,0 = 100 points */
#header { color: red; }
/* 0,1,1,1 = 111 points */
#header p.highlight { color: orange; }
/* 0,0,2,1 = 21 points */
.nav .menu-item { color: navy; }
/* 0,0,1,2 = 12 points */
ul li.active { color: gold; }
/* Inline style = 1000 points */
/* <p style="color: pink;">Text</p> */
Understanding !important
The !important declaration creates a separate specificity layer that overrides normal specificity calculations:
/* Normal specificity rules */
#header { color: red; } /* 100 points */
.content p { color: blue; } /* 11 points */
/* !important creates higher priority */
.content p { color: green !important; } /* Wins despite lower specificity */
#header { color: yellow !important; } /* Wins over normal #header rule */
/* !important vs !important follows normal specificity */
#header { color: purple !important; } /* 100 points + !important */
.header { color: orange !important; } /* 10 points + !important */
/* Purple wins because ID has higher specificity than class */
Understanding the Cascade
The cascade resolves conflicts using multiple layers of priority:
1. Source Order and Inheritance
/* Later rules override earlier ones with equal specificity */
.button { background: blue; }
.button { background: red; } /* This wins - same specificity, later in source */
/* Inheritance flows from parent to child */
.container {
color: gray; /* Inherited by children */
font-family: Arial; /* Inherited by children */
border: 1px solid; /* NOT inherited */
}
.container p {
/* Inherits color: gray and font-family: Arial */
/* Does NOT inherit border */
}
2. Cascade Origins
CSS rules come from different sources with varying priority:
- User agent styles: Browser defaults (lowest priority)
- User styles: User’s personal stylesheet
- Author styles: Developer’s CSS (highest priority)
/* Browser default (user agent) */
p { margin: 1em 0; }
/* Developer stylesheet (author) - overrides browser default */
p { margin: 0.5em 0; }
/* User stylesheet - can override author styles with !important */
p { margin: 2em 0 !important; }
Complex Specificity Scenarios
Pseudo-classes and Attribute Selectors
/* 0,0,1,1 = 11 points */
a:hover { color: red; }
/* 0,0,2,1 = 21 points */
a.button:hover { color: blue; }
/* 0,0,1,1 = 11 points */
input[type="text"] { border: 1px solid; }
/* 0,0,2,1 = 21 points */
.form input[type="text"] { border: 2px solid; }
/* 0,1,1,1 = 111 points */
#contact input[type="email"] { border: 3px solid; }
Combinators Don’t Add Specificity
/* 0,0,0,2 = 2 points (combinators like > don't count) */
div > p { color: blue; }
/* 0,0,0,3 = 3 points */
div p span { color: green; }
/* 0,0,1,2 = 12 points */
.content > p { color: red; }
Practical Applications and Common Patterns
Strategic Specificity Management
/* Low specificity base styles */
.button {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
}
/* Modifier classes with same specificity level */
.button--large {
padding: 0.75rem 1.5rem;
font-size: 1.1rem;
}
.button--danger {
background: #dc3545;
}
/* Context-specific overrides with higher specificity */
.sidebar .button {
width: 100%;
margin-bottom: 0.5rem;
}
/* State-based styles */
.button:hover {
opacity: 0.9;
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
Common Misconceptions
-
Misconception: More selectors always mean higher specificity Reality: It’s about the types of selectors, not the quantity
-
Misconception: !important always wins Reality: !important rules still follow specificity hierarchy among themselves
-
Misconception: Inline styles can’t be overridden Reality: They can be overridden by !important declarations in stylesheets
5. Live Coding Demonstration (20-25 minutes)
Example 1: Basic Specificity Conflicts
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Specificity Demonstration</title>
<style>
/* Let's create competing rules and see which wins */
/* 0,0,0,1 = 1 point */
p {
color: blue;
background: #f0f0f0;
padding: 10px;
margin: 10px 0;
}
/* 0,0,1,0 = 10 points */
.highlight {
color: green;
font-weight: bold;
}
/* 0,0,1,1 = 11 points */
p.highlight {
color: purple;
text-decoration: underline;
}
/* 0,1,0,0 = 100 points */
#special {
color: red;
font-size: 1.2em;
}
/* 0,1,1,1 = 111 points */
#special.highlight p {
color: orange;
font-style: italic;
}
/* Trying to override with more element selectors */
/* 0,0,0,4 = 4 points - still loses to class! */
html body div p {
color: navy;
}
/* Using !important */
.important-override {
color: pink !important;
background: yellow !important;
}
/* Even high specificity loses to !important */
#special.highlight.important-override {
color: brown; /* This won't work */
}
/* But !important with higher specificity wins */
#special.important-override {
color: darkgreen !important; /* This wins over .important-override */
}
</style>
</head>
<body>
<div>
<p>Basic paragraph - should be blue (1 point)</p>
<p class="highlight">
Paragraph with class - should be green (10 points)
</p>
<p class="highlight">
Another class paragraph, but also a p.highlight rule exists - should be purple (11 points)
</p>
<p id="special">
Paragraph with ID - should be red (100 points)
</p>
<div id="special" class="highlight">
<p>Nested paragraph - should be orange (111 points)</p>
</div>
<p class="important-override">
Paragraph with !important class - should be pink with yellow background
</p>
<p id="special" class="important-override">
ID + !important class - should be dark green (higher specificity !important wins)
</p>
<p style="color: hotpink;">
Inline style paragraph - should be hot pink (1000 points)
</p>
<p style="color: hotpink;" class="important-override">
Inline + !important class - should be pink (!important beats inline)
</p>
</div>
</body>
</html>
Explanation:
- Lines 8-13: Base element selector provides foundation styling (1 point)
- Lines 15-19: Class selector overrides text color (10 points beats 1 point)
- Lines 21-25: Combined element + class selector wins over just class (11 points beats 10 points)
- Lines 27-31: ID selector beats all previous rules (100 points)
- Lines 33-37: ID + class + element combination has highest normal specificity (111 points)
Example 2: Real-World Specificity Management
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Practical Specificity Example</title>
<style>
/* BEM methodology keeps specificity flat and predictable */
/* Base component styles - low specificity */
.card {
background: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.card__header {
border-bottom: 1px solid #eee;
padding-bottom: 0.5rem;
margin-bottom: 1rem;
}
.card__title {
margin: 0;
font-size: 1.25rem;
color: #333;
}
.card__content {
color: #666;
line-height: 1.6;
}
/* Modifier classes - same specificity level */
.card--featured {
border-color: #007bff;
border-width: 2px;
}
.card--danger {
border-color: #dc3545;
background: #fff5f5;
}
.card--large {
padding: 2rem;
font-size: 1.1rem;
}
/* Context-specific overrides - slightly higher specificity */
.sidebar .card {
margin: 0.5rem 0;
font-size: 0.9rem;
}
.sidebar .card__title {
font-size: 1rem;
}
/* State classes */
.card:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
transform: translateY(-1px);
transition: all 0.3s ease;
}
.card--disabled {
opacity: 0.6;
pointer-events: none;
}
/* Bad example: high specificity that's hard to override */
.page .content .main .card.featured#special-card {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
color: white;
}
/* Good example: utility classes with !important for overrides */
.u-text-center { text-align: center !important; }
.u-margin-none { margin: 0 !important; }
.u-hidden { display: none !important; }
/* Debugging styles */
.debug-specificity * {
outline: 1px solid red;
position: relative;
}
.debug-specificity *:before {
content: attr(class);
position: absolute;
top: -20px;
left: 0;
background: red;
color: white;
font-size: 10px;
padding: 2px 4px;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="container">
<h1>Specificity Management Examples</h1>
<!-- Basic card -->
<div class="card">
<div class="card__header">
<h2 class="card__title">Basic Card</h2>
</div>
<div class="card__content">
<p>This card uses low-specificity BEM classes for easy maintainability.</p>
</div>
</div>
<!-- Modified cards -->
<div class="card card--featured">
<div class="card__header">
<h2 class="card__title">Featured Card</h2>
</div>
<div class="card__content">
<p>This card has a modifier class that adds the blue border.</p>
</div>
</div>
<div class="card card--danger card--large">
<div class="card__header">
<h2 class="card__title">Large Danger Card</h2>
</div>
<div class="card__content">
<p>This card combines multiple modifier classes effectively.</p>
</div>
</div>
<!-- Sidebar context -->
<div class="sidebar">
<div class="card">
<div class="card__header">
<h3 class="card__title">Sidebar Card</h3>
</div>
<div class="card__content">
<p>This card is styled differently in the sidebar context.</p>
</div>
</div>
</div>
<!-- Problematic high specificity -->
<div class="page">
<div class="content">
<div class="main">
<div class="card featured" id="special-card">
<div class="card__header">
<h2 class="card__title">High Specificity Problem</h2>
</div>
<div class="card__content">
<p>This card is hard to override due to high specificity selector.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Utility class examples -->
<div class="card u-text-center">
<div class="card__header">
<h2 class="card__title">Centered Card</h2>
</div>
<div class="card__content">
<p>This card uses a utility class for centering.</p>
</div>
</div>
</div>
</body>
</html>
Key Points:
- Lines 7-29: BEM methodology keeps all component styles at the same specificity level
- Lines 31-43: Modifier classes maintain same specificity as base classes
- Lines 45-52: Context-specific styles use minimal specificity increase
- Lines 63-67: Example of problematic high specificity that should be avoided
- Lines 69-72: Utility classes with !important for reliable overrides
Example 3: Debugging Specificity with Developer Tools
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Specificity Debugging</title>
<style>
/* Complex competing rules to debug */
.nav { background: lightblue; }
nav.navigation { background: lightcoral; }
#main-nav { background: lightgreen; }
.header .nav { background: lightyellow; }
.header nav.navigation { background: lightpink; }
/* Button specificity conflicts */
button {
background: gray;
color: white;
border: none;
padding: 10px 20px;
}
.btn { background: blue; }
.button { background: green; }
.btn.primary { background: red; }
#submit-btn { background: purple; }
.form .btn { background: orange; }
.form .btn.primary { background: darkred; }
/* Pseudo-class specificity */
.btn:hover { background: yellow; }
.btn.primary:hover { background: darkblue; }
#submit-btn:hover { background: magenta; }
</style>
</head>
<body>
<div class="header">
<nav class="nav navigation" id="main-nav">
<p>Check which background color wins!</p>
</nav>
</div>
<div class="form">
<button class="btn">Regular Button</button>
<button class="btn button">Conflicting Classes</button>
<button class="btn primary">Primary Button</button>
<button class="btn primary" id="submit-btn">Submit Button</button>
</div>
<script>
// JavaScript to help analyze specificity
function calculateSpecificity(selector) {
const specificity = [0, 0, 0, 0];
// Count IDs
specificity[1] = (selector.match(/#[\w-]+/g) || []).length;
// Count classes, attributes, pseudo-classes
specificity[2] = (selector.match(/\.[\w-]+|:\w+|\[[\w-="']+\]/g) || []).length;
// Count elements and pseudo-elements
specificity[3] = (selector.match(/^[\w-]+|(?:\s|>|\+|~)[\w-]+/g) || []).length;
return specificity;
}
function analyzeSpecificity() {
const selectors = [
'.nav',
'nav.navigation',
'#main-nav',
'.header .nav',
'.header nav.navigation'
];
console.log('Navigation Specificity Analysis:');
selectors.forEach(selector => {
const spec = calculateSpecificity(selector);
console.log(`${selector}: ${spec.join(',')}`);
});
}
// Run analysis when page loads
document.addEventListener('DOMContentLoaded', analyzeSpecificity);
</script>
</body>
</html>
Debugging Common Specificity Issues
/* Problem: Overqualified selectors */
html body .container .content .article p.text {
color: blue; /* Unnecessarily high specificity */
}
/* Solution: Use minimal necessary specificity */
.article-text {
color: blue; /* Much more maintainable */
}
/* Problem: !important abuse */
.button {
background: blue !important;
color: white !important;
padding: 10px !important;
}
/* Solution: Fix specificity hierarchy */
.btn {
background: blue;
color: white;
padding: 10px;
}
.btn--primary {
background: green;
}
/* Problem: ID overuse */
#header #nav #menu-item {
color: red; /* Very hard to override */
}
/* Solution: Use classes */
.header-nav__item {
color: red; /* Easy to work with */
}
6. Hands-On Practice (30-40 minutes)
Exercise 1: Specificity Calculation Practice (10 minutes)
Objective: Practice calculating specificity values for different selectors.
Instructions:
- Calculate the specificity for each selector below
- Arrange them in order from lowest to highest specificity
- Predict which rule would win in conflicts
Selectors to Calculate:
/* Calculate specificity for each selector */
p
.highlight
#main
p.highlight
.nav .menu-item
#header .nav a
div > p.content
.btn:hover
input[type="text"]
#form input.required:focus
.container .card .title
body .wrapper #main .content
.btn.primary.large
Solution:
/* Specificity calculations (a,b,c,d format) */
p /* 0,0,0,1 = 1 */
.highlight /* 0,0,1,0 = 10 */
input[type="text"] /* 0,0,1,1 = 11 */
p.highlight /* 0,0,1,1 = 11 */
.btn:hover /* 0,0,2,0 = 20 */
.nav .menu-item /* 0,0,2,0 = 20 */
div > p.content /* 0,0,1,2 = 12 */
.btn.primary.large /* 0,0,3,0 = 30 */
.container .card .title /* 0,0,3,0 = 30 */
#main /* 0,1,0,0 = 100 */
#header .nav a /* 0,1,1,1 = 111 */
#form input.required:focus /* 0,1,2,1 = 121 */
body .wrapper #main .content /* 0,1,2,1 = 121 */
Exercise 2: Resolving Specificity Conflicts (15 minutes)
Objective: Debug and fix specificity conflicts in a realistic scenario.
Instructions:
- Identify why certain styles aren’t being applied
- Fix the conflicts using proper specificity management
- Avoid using !important unless absolutely necessary
Starter Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Specificity Exercise</title>
<style>
/* Base styles */
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
cursor: pointer;
}
/* These styles should work but might not due to specificity */
.btn-large {
padding: 15px 30px;
font-size: 1.2em;
}
.btn-danger {
background: #dc3545;
}
.btn-success {
background: #28a745;
}
/* Context styles that might cause conflicts */
.header .btn {
background: #6c757d;
border: 1px solid #ccc;
}
.form .btn {
width: 100%;
margin-bottom: 10px;
}
/* ID that might override everything */
#special-button {
background: purple;
color: yellow;
}
/* Hover states */
.btn:hover {
opacity: 0.9;
}
.btn-danger:hover {
background: #bd2130;
}
</style>
</head>
<body>
<div class="header">
<button class="btn btn-large">Large Header Button</button>
<button class="btn btn-danger">Danger Header Button</button>
</div>
<div class="form">
<button class="btn btn-success">Success Form Button</button>
<button class="btn btn-large btn-danger">Large Danger Form Button</button>
<button class="btn" id="special-button">Special Button</button>
</div>
</body>
</html>
Solution:
/* Fixed version with proper specificity management */
/* Base styles - keep specificity low */
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
cursor: pointer;
}
/* Modifier classes - same specificity level as base */
.btn--large {
padding: 15px 30px;
font-size: 1.2em;
}
.btn--danger {
background: #dc3545;
}
.btn--success {
background: #28a745;
}
/* Context styles - minimal specificity increase */
.header .btn {
border: 1px solid #ccc; /* Only non-conflicting properties */
}
.form .btn {
width: 100%;
margin-bottom: 10px; /* Only layout properties */
}
/* Use modifier classes instead of ID */
.btn--special {
background: purple;
color: yellow;
}
/* Hover states with proper specificity */
.btn:hover {
opacity: 0.9;
}
.btn--danger:hover {
background: #bd2130;
}
Exercise 3: Building a Maintainable CSS Architecture (15 minutes)
Objective: Create a CSS system that avoids specificity conflicts.
Challenge: Build a complete button system with:
- Base button styles
- Size variations (small, medium, large)
- Color variations (primary, secondary, success, danger, warning)
- State variations (disabled, loading)
- Context-specific adjustments
Extension Ideas:
- Add component combinations (button groups)
- Implement responsive button sizing
- Create icon button variations
- Add animation states
7. Common Pitfalls and Troubleshooting (10 minutes)
Frequent Mistakes
-
Problem: Over-qualifying selectors unnecessarily Cause: Adding more specificity than needed for styling Solution: Use the minimum specificity required; start with single classes
-
Problem: !important overuse leading to maintenance nightmares Cause: Using !important as a quick fix instead of understanding specificity Solution: Restructure CSS hierarchy; use !important only for utility classes
-
Problem: ID selectors creating unmaintainable specificity spikes Cause: Using IDs for styling instead of just JavaScript hooks Solution: Reserve IDs for JavaScript; use classes for all styling
-
Problem: Inline styles making components inflexible Cause: Adding style attributes directly to HTML Solution: Move all styling to CSS files; use CSS custom properties for dynamic values
Debugging Tips
- Use browser developer tools to inspect computed styles and see which rules are overridden
- Look for crossed-out styles in the developer tools to identify specificity conflicts
- Use the specificity calculator websites or browser extensions for complex selectors
- Add temporary border or background colors to verify which rules are being applied
- Check the “Computed” tab in developer tools to see final calculated values
8. Best Practices and Professional Tips (5 minutes)
Industry Standards
- Keep specificity low: Start with single classes and add specificity only when needed
- Avoid IDs for styling: Use IDs only for JavaScript hooks and fragment links
- Use !important sparingly: Reserve for utility classes and third-party overrides only
- Follow naming conventions: BEM, OOCSS, or similar methodologies prevent specificity wars
CSS Architecture Guidelines
/* Good: Flat specificity hierarchy */
.component { }
.component--modifier { }
.component__element { }
.component__element--modifier { }
/* Bad: Escalating specificity */
.page .section .component .element { }
.page .section .component .element.modified { }
Next Steps in Your Learning Journey
- CSS Methodologies: Study BEM, OOCSS, SMACSS for organized CSS architecture
- CSS-in-JS: Explore modern approaches that solve specificity differently
- Design Systems: Learn how component libraries manage specificity at scale
- Performance: Understand how specificity affects CSS parsing and rendering speed
9. Summary and Review (5 minutes)
Key Takeaways
- Specificity is calculated mathematically using inline styles (1000), IDs (100), classes/attributes/pseudo-classes (10), and elements (1)
- The cascade resolves conflicts using specificity first, then source order for equal specificity
- !important creates a separate specificity layer but should be used sparingly and strategically
- Maintainable CSS keeps specificity low and predictable through methodologies like BEM
Quick Review Questions
- What’s the specificity value of
.nav ul li a:hover? - Why should you avoid using IDs for styling?
- In what order does the cascade resolve conflicting CSS rules?
Answers:
- 0,0,2,3 = 23 points (class + pseudo-class + 3 elements)
- IDs create high specificity (100 points) that’s hard to override and maintain
- Importance (!important), then specificity, then source order
For Instructors
Teaching Tips
- Use visual tools like specificity calculators to make the concept tangible
- Demonstrate conflicts live in browser developer tools to show real-time resolution
- Emphasize that specificity is about strategy, not just rules
- Connect specificity to maintainability and team collaboration
Assessment Ideas
- Specificity Quiz: Students calculate and compare selector specificity
- Debug Challenge: Provide broken CSS with specificity conflicts to fix
- Architecture Review: Students design a CSS system with proper specificity hierarchy
Adaptation Notes
- For Beginners: Focus on basic calculation before diving into advanced scenarios
- For Advanced Students: Include CSS-in-JS and modern tooling approaches to specificity
- Online Delivery: Use screen sharing with browser inspector to clearly show specificity resolution
- Time Management: Ensure adequate hands-on practice as specificity is best learned through experience