3.9: CSS Best Practices
Add motion and interactivity to your websites using CSS transitions, transforms, and keyframe animations. Learn how to create smooth hover effects, rotate and scale elements, and build engaging animated sequences.
1. CSS Organization
File Structure
Single file (small projects):
styles.css
Modular structure (medium projects):
css/
├── reset.css
├── variables.css
├── base.css
├── layout.css
├── components.css
└── utilities.css
Component-based (large projects):
css/
├── base/
│ ├── reset.css
│ ├── typography.css
│ └── variables.css
├── components/
│ ├── button.css
│ ├── card.css
│ └── navigation.css
├── layout/
│ ├── grid.css
│ ├── header.css
│ └── footer.css
└── utilities/
├── spacing.css
└── colors.css
Import Order
/* 1. Reset/Normalize */
@import 'reset.css';
/* 2. Variables */
@import 'variables.css';
/* 3. Base styles */
@import 'base.css';
@import 'typography.css';
/* 4. Layout */
@import 'layout.css';
/* 5. Components */
@import 'components/buttons.css';
@import 'components/cards.css';
/* 6. Utilities */
@import 'utilities.css';
2. Naming Conventions
BEM (Block Element Modifier)
Block: Independent component Element: Part of a block Modifier: Variation of block or element
/* Block */
.card { }
/* Element */
.card__header { }
.card__body { }
.card__footer { }
/* Modifier */
.card--featured { }
.card--large { }
.card__header--dark { }
HTML:
<div class="card card--featured">
<div class="card__header card__header--dark">
<h2 class="card__title">Title</h2>
</div>
<div class="card__body">
Content
</div>
<div class="card__footer">
<button class="card__button">Action</button>
</div>
</div>
Benefits:
- ✅ Clear relationship between classes
- ✅ Avoids specificity conflicts
- ✅ Self-documenting
SMACSS (Scalable and Modular Architecture)
Categories:
/* 1. Base - Element selectors only */
html, body, h1, p { }
/* 2. Layout - Major sections (prefix: l-) */
.l-header { }
.l-sidebar { }
.l-main { }
/* 3. Module - Reusable components */
.card { }
.button { }
.nav { }
/* 4. State - Dynamic states (prefix: is-) */
.is-active { }
.is-hidden { }
.is-loading { }
/* 5. Theme - Color schemes (prefix: theme-) */
.theme-dark { }
.theme-light { }
Utility-First (Tailwind-style)
/* Utility classes */
.flex { display: flex; }
.justify-center { justify-content: center; }
.p-4 { padding: 1rem; }
.text-center { text-align: center; }
.bg-primary { background: var(--primary-color); }
/* Responsive utilities */
.md\:flex { }
@media (min-width: 768px) {
.md\:flex { display: flex; }
}
3. CSS Variables (Custom Properties)
Defining Variables
:root {
/* Colors */
--primary-color: #42b883;
--secondary-color: #35495e;
--success-color: #4caf50;
--error-color: #f44336;
/* Spacing */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
/* Typography */
--font-primary: 'Helvetica Neue', Arial, sans-serif;
--font-secondary: Georgia, serif;
/* Sizes */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.25rem;
--text-xl: 1.5rem;
/* Border radius */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.1);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
/* Transitions */
--transition-fast: 0.15s ease;
--transition-base: 0.3s ease;
--transition-slow: 0.5s ease;
}
Using Variables
.button {
background: var(--primary-color);
padding: var(--space-md) var(--space-lg);
border-radius: var(--radius-md);
transition: all var(--transition-base);
box-shadow: var(--shadow-md);
}
/* With fallback */
.element {
color: var(--custom-color, #333);
}
Theming with Variables
/* Light theme (default) */
:root {
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--text-primary: #333333;
--text-secondary: #666666;
}
/* Dark theme */
[data-theme="dark"] {
--bg-primary: #1a1a1a;
--bg-secondary: #2a2a2a;
--text-primary: #f5f5f5;
--text-secondary: #cccccc;
}
/* Apply theme */
body {
background: var(--bg-primary);
color: var(--text-primary);
}
JavaScript theme toggle:
document.documentElement.setAttribute('data-theme', 'dark');
4. Specificity Management
Keep Specificity Low
/* Bad - high specificity */
body div.container div.content ul li a.link {
color: blue;
}
/* Good - low specificity */
.nav-link {
color: blue;
}
Avoid ID Selectors for Styling
/* Bad - hard to override */
#header {
background: blue;
}
/* Good - use classes */
.header {
background: blue;
}
Use Classes, Not Elements
/* Bad - too generic */
div {
margin-bottom: 1rem;
}
/* Good - specific classes */
.card {
margin-bottom: 1rem;
}
The Specificity Pyramid
!important ← Avoid
↑
Inline ← Avoid
↑
IDs ← Avoid
↑
Classes/Attrs ← Use these
↑
Elements ← Base styles only
5. DRY Principle (Don't Repeat Yourself)
Extract Common Patterns
/* Bad - repetitive */
.button-primary {
padding: 12px 24px;
border-radius: 4px;
font-weight: 600;
transition: all 0.3s;
background: blue;
}
.button-secondary {
padding: 12px 24px;
border-radius: 4px;
font-weight: 600;
transition: all 0.3s;
background: gray;
}
/* Good - shared base */
.button {
padding: 12px 24px;
border-radius: 4px;
font-weight: 600;
transition: all 0.3s;
}
.button--primary {
background: blue;
}
.button--secondary {
background: gray;
}
Use Variables for Repeated Values
/* Bad */
.header {
padding: 20px;
margin-bottom: 20px;
}
.footer {
padding: 20px;
margin-top: 20px;
}
/* Good */
:root {
--spacing-unit: 20px;
}
.header {
padding: var(--spacing-unit);
margin-bottom: var(--spacing-unit);
}
.footer {
padding: var(--spacing-unit);
margin-top: var(--spacing-unit);
}
6. Performance Optimization
Minimize Selectors
/* Slow */
div.container > ul > li > a { }
/* Fast */
.nav-link { }
Avoid Universal Selector
/* Slow - applies to everything */
* {
box-sizing: border-box;
}
/* Better - be specific */
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
Use Shorthand Properties
/* Long */
.element {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;
}
/* Short */
.element {
margin: 10px 20px;
}
Remove Unused CSS
Tools:
- PurgeCSS
- UnCSS
- Chrome DevTools Coverage tab
Critical CSS
<!-- Inline critical CSS -->
<style>
/* Above-the-fold styles */
.header { ... }
.hero { ... }
</style>
<!-- Defer non-critical CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
7. Accessibility Best Practices
Color Contrast
/* Bad - poor contrast */
.text {
color: #ccc;
background: #fff;
/* Contrast ratio: 1.6:1 - fails WCAG */
}
/* Good - sufficient contrast */
.text {
color: #333;
background: #fff;
/* Contrast ratio: 12.6:1 - passes WCAG AAA */
}
Focus Styles
/* Bad - removing outline */
button:focus {
outline: none;
}
/* Good - custom focus indicator */
button:focus {
outline: 2px solid var(--primary-color);
outline-offset: 2px;
}
/* Better - focus-visible (modern) */
button:focus-visible {
outline: 2px solid var(--primary-color);
outline-offset: 2px;
}
Hidden Content
/* Visually hidden but screen reader accessible */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Hidden from everyone */
.hidden {
display: none;
}
/* Visually hidden, removes from accessibility tree */
.invisible {
visibility: hidden;
}
Responsive Text
/* Minimum 16px for readability */
body {
font-size: 16px;
}
/* Allow user zoom */
html {
-webkit-text-size-adjust: 100%;
}
/* Don't disable zoom */
/* Bad: user-scalable=no */
8. Comments and Documentation
Section Comments
/* ===================================
HEADER COMPONENT
=================================== */
.header {
/* styles */
}
/* ===================================
BUTTON COMPONENT
=================================== */
.button {
/* styles */
}
Inline Comments
.element {
/* Fix for IE11 flexbox bug */
flex-shrink: 0;
/* Prevent text selection on double-click */
user-select: none;
/* TODO: Update color to match brand guidelines */
color: #333;
/* NOTE: This z-index must be higher than modal overlay */
z-index: 1001;
}
Documentation Comments
/**
* Button Component
*
* Usage:
* <button class="button button--primary">Click me</button>
*
* Modifiers:
* --primary Primary action button
* --secondary Secondary action button
* --large Larger button size
* --small Smaller button size
*
* States:
* :hover Hover state
* :active Active/pressed state
* :disabled Disabled state
*/
.button { }
9. Common Patterns
Container Pattern
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--space-md);
}
/* Fluid container */
.container-fluid {
width: 100%;
padding: 0 var(--space-md);
}
Card Pattern
.card {
background: white;
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
padding: var(--space-lg);
transition: all var(--transition-base);
}
.card:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-4px);
}
Spacing Utilities
/* Margin utilities */
.m-0 { margin: 0; }
.m-1 { margin: 0.25rem; }
.m-2 { margin: 0.5rem; }
.m-3 { margin: 1rem; }
.m-4 { margin: 1.5rem; }
.mt-3 { margin-top: 1rem; }
.mr-3 { margin-right: 1rem; }
.mb-3 { margin-bottom: 1rem; }
.ml-3 { margin-left: 1rem; }
/* Padding utilities */
.p-0 { padding: 0; }
.p-1 { padding: 0.25rem; }
.p-2 { padding: 0.5rem; }
.p-3 { padding: 1rem; }
.p-4 { padding: 1.5rem; }
10. Debugging CSS
Browser DevTools
Chrome DevTools:
- Inspect element (F12)
- Styles panel shows all applied CSS
- Computed panel shows final values
- Box model visualizer
Common issues:
- Specificity conflicts (strikethrough styles)
- Invalid values (yellow warning)
- Overridden properties (crossed out)
Debugging Techniques
Outline Everything:
* {
outline: 1px solid red;
}
Background Colors:
.container { background: rgba(255, 0, 0, 0.1); }
.section { background: rgba(0, 255, 0, 0.1); }
.element { background: rgba(0, 0, 255, 0.1); }
Console Logging (via DevTools):
// Get computed style
getComputedStyle(document.querySelector('.element')).display
// Check specificity
// Use DevTools Styles panel
11. CSS Linting
Stylelint Configuration
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": 2,
"color-hex-case": "lower",
"color-hex-length": "short",
"selector-max-id": 0,
"selector-max-specificity": "0,3,0",
"declaration-no-important": true,
"max-nesting-depth": 3
}
}
12. Practical Exercises
Exercise 3.9.1: Refactor CSS
Take messy CSS and refactor it:
- Apply BEM naming
- Extract variables
- Reduce specificity
- Add comments
Exercise 3.9.2: Build a Component Library
Create reusable components:
- Buttons (variants and states)
- Cards (with modifiers)
- Form inputs
- Document with comments
Exercise 3.9.3: Performance Audit
Audit a stylesheet:
- Identify unused CSS
- Simplify selectors
- Add critical CSS
- Measure improvements
Exercise 3.9.4: Accessibility Review
Review CSS for accessibility:
- Check color contrast
- Add focus indicators
- Test with screen reader
- Fix issues
13. Knowledge Check
Question 1: What is BEM and why use it?
Show answer
BEM (Block Element Modifier) is a naming convention that creates clear relationships between classes, avoids specificity issues, and makes CSS more maintainable.Question 2: Why keep specificity low?
Show answer
Low specificity makes CSS easier to override and maintain. High specificity leads to specificity wars and requires !important to override.Question 3: What are the benefits of CSS variables?
Show answer
CSS variables enable theming, reduce repetition, make updates easier, and can be changed with JavaScript for dynamic styling.Question 4: Which CSS properties should you avoid animating?
Show answer
Avoid animating width, height, top, left, margin, padding. Use transform and opacity instead for better performance.Question 5: What's the minimum color contrast ratio for normal text?
Show answer
4.5:1 for normal text, 3:1 for large text (18pt+ or 14pt+ bold) according to WCAG AA standards.14. Key Takeaways
✅ Organization - Structure CSS files logically ✅ Naming - Use BEM or SMACSS for consistency ✅ Variables - Centralize values for maintainability ✅ Specificity - Keep it low for flexibility ✅ DRY - Extract common patterns ✅ Performance - Minimize selectors, remove unused CSS ✅ Accessibility - Ensure contrast, focus styles, semantic markup ✅ Comments - Document complex code ✅ Debugging - Use DevTools effectively ✅ Linting - Enforce standards automatically
15. CSS Checklist
Before pushing code:
- Follows naming convention (BEM/SMACSS)
- Uses CSS variables for common values
- Low specificity (avoid IDs, deep nesting)
- No !important (unless necessary)
- Accessible (contrast, focus styles)
- Commented where necessary
- No unused CSS
- Performance optimized
- Mobile responsive
- Browser tested
16. Further Resources
Methodologies:
Tools:
Guides:
Next Steps
Congratulations! You've completed Phase 3: CSS Styling & Layout.
You now have comprehensive knowledge of:
- CSS fundamentals and syntax
- Selectors and specificity
- Box model and layout
- Flexbox for 1D layouts
- Grid for 2D layouts
- Responsive design
- Typography and colors
- Transitions and animations
- Best practices and patterns
Ready for Phase 4? In Phase 4: JavaScript Interactivity, you'll learn to add dynamic behavior and interactivity to your websites.
Phase 3 Project
Milestone Project 2: Responsive Landing Page
Build a complete responsive landing page featuring:
Requirements:
- Semantic HTML structure
- Hero section with gradient background
- Features grid using Flexbox or Grid
- Responsive navigation (mobile hamburger menu)
- Contact form with styling
- Card components with hover effects
- Typography system with web fonts
- Mobile-responsive (mobile-first approach)
- Smooth transitions and animations
- CSS variables for theming
- Follows BEM naming convention
- Accessible (WCAG AA contrast, focus states)
Deliverables:
- HTML file with semantic markup
- Well-organized CSS (modular structure)
- Responsive breakpoints (mobile, tablet, desktop)
- Browser-tested (Chrome, Firefox, Safari)
- GitHub repository with code