CSS Basics — Styling the Web

Status: Active Last Updated: 2026-08-29 Category: Web — CSS Prerequisites: HTML basics Tags: css, selectors, specificity, box-model, flexbox, grid, responsive

Summary

CSS (Cascading Style Sheets) controls how HTML looks: colors, layout, fonts, spacing, animations. This article covers selectors, the box model, flexbox, grid, and responsive design.

What You'll Learn

Table of Contents

  1. Architectural Overview & Core Schema
  2. Deep Dive & Implementation
  3. Anti-Patterns & Common Pitfalls
  4. Independent Challenge
  5. Consolidation & Key Invariants
  6. Next Steps

1. Architectural Overview & Core Schema

Foundational theory, system mechanics, and high-level design.

Selectors and Specificity

CSS selectors target elements to style:

/* element selector */
h1 { color: red; }

/* class selector */
.button { background: blue; }

/* id selector */
#header { font-size: 24px; }

/* attribute selector */
input[type="text"] { border: 1px solid gray; }

/* pseudo-class */
a:hover { color: green; }

/* descendant */
nav a { color: white; }

Specificity determines which rule wins when multiple match:

The higher specificity wins. !important overrides everything (use sparingly).


The Box Model

Every element is a rectangular box with four layers (from inside out):

+---------------------+
|       margin        |  (space outside the border)
+---------------------+
|       border        |  (line around the element)
+---------------------+
|      padding        |  (space inside the border)
+---------------------+
|       content       |  (the actual content)
+---------------------+
.box {
    width: 200px;        /* content width */
    padding: 20px;        /* inside the border */
    border: 1px solid;   /* line around */
    margin: 10px;         /* outside the border */
    box-sizing: border-box; /* width includes padding+border */
}

box-sizing: border-box is almost always what you want — width: 200px becomes the visible width including padding and border.


2. Deep Dive & Implementation

Technical implementation, fully commented code blocks, and step-by-step logic.

Guided Checkpoint

Inspect specificity and computed styles in the browser:

// In DevTools console — list all computed styles for an element
const el = document.querySelector('.card');
const styles = getComputedStyle(el);
console.log('display:', styles.display);
console.log('width:', styles.width);
console.log('padding:', styles.padding);
console.log('margin:', styles.margin);

// Inspect the cascade in the Elements > Styles pane
// Click "Computed" tab to see resolved values
// Click any property to jump to its source rule

// In the console, show the element's inline styles
console.log('Inline styles:', el.style.cssText);

Deep Dive — Flexbox

Flexbox arranges items in one direction (row or column). Apply display: flex to the container. justify-content aligns along the main axis; align-items aligns along the cross axis. flex-grow, flex-shrink, flex-basis control item sizing. gap sets spacing between items without margins.

/* Card row with equal-width items */
.cards {
    display: flex;
    gap: 1rem;
    justify-content: space-between;
    align-items: stretch;
}
.card {
    flex: 1 1 0; /* grow, shrink, basis — equal width */
    min-width: 200px;
}

/* Centering content */
.centered {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
}

/* Responsive wrapping */
.row {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.row > * { flex: 1 1 300px; }

Deep Dive — CSS Grid

CSS Grid creates two-dimensional layouts (rows and columns). grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) creates responsive columns without media queries. grid-area lets you name regions and place items by name.

/* Responsive auto-grid */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
}

/* Explicit grid */
.layout {
    display: grid;
    grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
    grid-template-columns: 250px 1fr;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
}
.layout header  { grid-area: header; }
.layout aside   { grid-area: sidebar; }
.layout main    { grid-area: main; }
.layout footer  { grid-area: footer; }

Deep Dive — Responsive Design

Responsive design adapts layout to viewport size. Start with mobile-first CSS (default styles, enhance with media queries). max-width on containers prevents over-stretching on large screens. clamp(min, preferred, max) smoothly scales values.

/* Mobile-first default */
.page { padding: 1rem; }

/* Tablet and up */
@media (min-width: 640px) {
    .page { padding: 2rem; }
    .sidebar { display: flex; }
}

/* Desktop */
@media (min-width: 1024px) {
    .page { max-width: 1200px; margin: 0 auto; }
}

/* Fluid typography */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }

/* Fluid spacing */
.card { padding: clamp(0.75rem, 2vw, 2rem); }

Use relative units: rem for font sizes/accessibility, % or vw/vh for layout, em for component-local spacing. Avoid fixed pixel widths for containers.

Deep Dive — CSS Custom Properties

Custom properties (CSS variables) store values for reuse and theming. Defined on :root for global scope, overridable per component. Reference with var(--name, fallback).

:root {
    --color-bg: #ffffff;
    --color-text: #1a1a1a;
    --color-accent: #3b82f6;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --space-lg: 2rem;
    --radius: 0.375rem;
    --font-body: system-ui, sans-serif;
}

body {
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
}

.btn {
    background: var(--color-accent);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius);
    color: white;
}

/* Dark theme override */
[data-theme="dark"] {
    --color-bg: #0f172a;
    --color-text: #e2e8f0;
}

Custom properties enable design tokens, runtime theming, and DRY stylesheets. Change --color-accent in one place and every .btn updates.

3. Anti-Patterns & Common Pitfalls

Documented failure modes and how to detect/prevent them.

Forgetting box-sizing: border-box

By default, CSS uses content-box: width: 200px sets the content width to 200px, and padding and border are added on top. A 200px wide box with 20px padding and a 1px border renders at 242px wide. This surprises developers and causes layout breakage when you add padding to fixed-width containers.

Fix: Set box-sizing: border-box globally:

*, *::before, *::after { box-sizing: border-box; }

With border-box, width is the total visible width including padding and border.

Specificity wars leading to !important abuse

When two rules conflict and neither can be overridden cleanly, developers reach for !important. Once one !important exists, another must be added to override it, and the cascade becomes unmanageable. Specificity should always win without !important.

Fix: Keep specificity low: prefer class selectors over ID selectors. Use a consistent naming convention (BEM, utility classes). Reserve !important only for utility overrides (e.g., .sr-only { position: absolute !important; }) and never for component styles.

Layout thrashing from reading and writing layout properties in a loop

Reading offsetWidth, getBoundingClientRect(), or getComputedStyle().width forces synchronous layout. Writing to a DOM property afterward forces another layout. A loop alternating reads and writes causes a reflow on every iteration.

Fix: Read all values first, store them, then write:

// BAD — reflow on each iteration
elements.forEach(el => {
  const h = el.offsetHeight;
  el.style.height = h * 2 + 'px'; // write triggers reflow
});

// GOOD — 1 reflow total
const heights = elements.map(el => el.offsetHeight);
requestAnimationFrame(() => elements.forEach((el, i) => el.style.height = heights[i] * 2 + 'px'));

Fixed pixel widths breaking responsive design

width: 1200px on a container looks correct on a desktop but causes horizontal scrolling on mobile. width: 100% with fixed padding also overflows the viewport. max-width is always safer for containers.

Fix:

.container { max-width: 1200px; width: 100%; margin: 0 auto; padding: 0 1rem; }

Always test at 375px (mobile) and 768px (tablet) viewport widths.

Using position: absolute for everything

Overusing position: absolute removes elements from the normal flow, making them hard to reason about. Adjacent content does not reflow around them, and overlapping z-index stacking becomes unpredictable.

Fix: Use flexbox or grid for layout first. Reserve position: absolute for overlays (modals, tooltips), badge overlays on cards, and elements that need to escape the flow intentionally.

Not scoping CSS or using overly generic class names

.button, .card, and .title are generic enough to collide across a large codebase. A class name collision means one CSS rule affects elements it shouldn't, causing invisible bugs.

Fix: Namespace with a component prefix (.card-header, .card-body, .card-footer via BEM, or .Card-header with CSS Modules). In projects using CSS Modules or CSS-in-JS, scoping is automatic.

4. Independent Challenge

A problem to solve without step-by-step guidance; promotes synthesis.

Build a responsive card grid layout from scratch without looking at the deep-dive code. Requirements:

  1. Use CSS Grid (grid-template-columns: repeat(auto-fit, minmax(..., 1fr))) to create a grid that reflows from 1 column (mobile) to 2 columns (tablet) to 3+ columns (desktop) without media queries
  2. Each card has: an image (use a placeholder via https://picsum.photos/seed/{n}/400/200), a heading, a body paragraph, and a "Read more" button
  3. All cards must be equal height in a row
  4. The card buttons must align to the bottom of the card regardless of how much text is in the body
  5. On mobile, cards stack vertically with no horizontal gap
  6. Add a dark-theme override ([data-theme="dark"]) that inverts card background and text colors

Constraints: No flexbox (use CSS Grid only for the layout). No Tailwind. Pure CSS.

5. Consolidation & Key Invariants

Bullet-list summary of the must-remember rules.

6. Next Steps

Sequenced links to dependent lessons, deeper dives, or production guides.


Change Log

Choose Theme

Your selection is saved locally.

Neural Cacophony
Aperture v2
Flux v1
Mosaic Chaos
Nexus v1
Nexus Zest
Prism v2
Synapse