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:

  1. Inspect element (F12)
  2. Styles panel shows all applied CSS
  3. Computed panel shows final values
  4. 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