Skip to content

CSS

CSS (Cascading Style Sheets) describes how elements should be presented, not what they are. It operates on the DOM tree produced by HTML parsing. CSS is declarative: you describe desired outcomes, and the browser decides how to achieve them. The complexity of CSS comes from rule interaction, not syntax. Understanding CSS means understanding how rules are resolved.

The CSS processing pipeline (mental model)

When CSS is applied, the browser performs these conceptual steps:

  • Parse CSS into the CSSOM
  • Match selectors against DOM elements
  • Resolve the cascade (which rule wins)
  • Compute final values (computed styles)
  • Apply layout algorithms
  • Paint and composite

Most bugs come from misunderstanding when and why a value is chosen.

The cascade (why CSS behaves the way it does)

CSS is designed so that many rules can apply to the same element at the same time. This is not a mistake; it is a core design goal. Without a deterministic conflict-resolution system, styling large documents would be impossible. The cascade defines how conflicts are resolved, not whether conflicts are allowed. When two rules both match an element, the cascade decides which one wins.

Importance (!important)

Rules marked with !important override normal rules, regardless of specificity or order.

Example:

.button {
color: blue;
}
.button {
color: red !important;
}

Result:

  • color: red wins, even though both selectors are equal.

Key points:

  • !important jumps to the top of the priority stack.
  • Multiple !important rules still compete using the remaining cascade steps.
  • It should be reserved for exceptional cases, not routine styling.

Why it is dangerous:

  • It bypasses the natural conflict resolution of CSS.
  • It makes future overrides harder, often requiring more !important.
  • It flattens the cascade into a brittle hierarchy.

Origin (where the rule comes from)

CSS rules come from different sources, called origins.

Ordered from weakest to strongest:

  • User agent styles (browser defaults)
  • User styles (user-defined preferences)
  • Author styles (your application’s CSS)

Example:

  • Browsers give

    a default font size.

  • Your stylesheet overrides that size.
  • The user may override both for accessibility reasons.

Key points:

  • Author styles usually win over browser defaults.
  • Accessibility tools rely on user styles being respected.
  • The origin layer exists to balance control between browser, user, and author.

This layer is rarely visible in day-to-day work, but it explains why browser defaults are easily overridden.

Specificity (how precise the selector is)

Specificity determines how targeted a selector is.

Simplified ranking (weak → strong):

  • Type selectors (p)
  • Class selectors (.card)
  • Attribute selectors ([disabled])
  • Pseudo-classes (:hover)
  • ID selectors (#main)

Example:

p {
color: black;
}
.article p {
color: gray;
}

Result:

  • .article p wins because it is more specific.

Key points:

  • Specificity compares selectors component by component, not by intuition.
  • A single ID selector outweighs many class selectors.
  • More specific selectors override less specific ones, even if they appear earlier.

Design implication:

  • High specificity makes styles hard to override later.
  • Low specificity keeps styles flexible and composable.

Source order (last rule wins)

If all previous steps are equal, the rule defined later wins.

Example:

.card {
background: white;
}
.card {
background: gray;
}

Result:

  • The second rule applies.

Key points:

  • CSS is read top-to-bottom.
  • This allows intentional overrides without increasing specificity.
  • Source order is the final tie-breaker, not the primary mechanism.

Good CSS often relies on source order instead of specificity escalation.

Putting it all together (mental model)

When multiple rules match an element, the browser asks:

  • Is one rule !important?
  • Which rule comes from the stronger origin?
  • Which selector is more specific?
  • Which rule appears later?

The first difference encountered decides the winner.

Why CSS conflicts are normal

CSS assumes:

  • Components will overlap
  • Rules will collide
  • Styles will be reused and extended

The cascade is how CSS scales without requiring global coordination.

Fighting the cascade leads to:

  • Over-specific selectors
  • Excessive !important
  • Fragile stylesheets

Designing with the cascade leads to:

  • Predictable overrides
  • Reusable components
  • Maintainable systems

Practical guidance

  • Prefer source order over specificity
  • Prefer specificity over !important
  • Use !important only when escaping external constraints
  • Treat specificity like technical debt

Key takeaway:

  • The cascade is not a problem to solve; it is the solution CSS provides.

Inheritance (what flows down the tree)

Some CSS properties inherit values from parent elements automatically.

Common inherited properties:

  • color
  • font-family
  • font-size
  • line-height

Common non-inherited properties:

  • margin
  • padding
  • border
  • width, height

Inheritance explains why setting styles high in the DOM is powerful and efficient.

The box model (fundamental to layout)

Every element is a rectangular box composed of:

  • Content
  • Padding
  • Border
  • Margin

Key properties:

  • box-sizing: content-box (default)
  • box-sizing: border-box (recommended)

With border-box:

  • Width and height include padding and border.
  • Layout becomes predictable.

Misunderstanding the box model causes sizing bugs and overflow issues.

Display types (how elements participate in layout)

The display property defines an element’s layout behavior.

Common values:

  • block → new line, full width
  • inline → flows with text, no box sizing
  • inline-block → inline flow with box model
  • none → removed from layout entirely

Advanced:

  • flex
  • grid
  • table

Changing display often changes layout more than any other property.

Positioning (coordinate systems)

CSS positioning controls how elements are placed relative to others.

Types:

  • static (default)
  • relative (offset from itself)
  • absolute (removed from flow, positioned relative to nearest positioned ancestor)
  • fixed (relative to viewport)
  • sticky (hybrid scroll-based behavior)

Key insight:

  • Positioned elements establish new containing blocks.
  • absolute does not mean “relative to the page”.

Flexbox (one-dimensional layout)

Flexbox is designed for one axis at a time (row or column).

Core concepts:

  • Flex container vs flex items
  • Main axis vs cross axis
  • Free space distribution

Key properties:

  • display: flex
  • flex-direction
  • justify-content
  • align-items
  • flex-grow, flex-shrink, flex-basis

Flexbox excels at alignment, spacing, and dynamic sizing.

Grid (two-dimensional layout)

Grid is designed for rows and columns simultaneously.

Core concepts:

  • Explicit vs implicit grid
  • Tracks, lines, and areas
  • Fractional units (fr)

Key properties:

  • display: grid
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • gap

Grid enables layouts that were previously very complex or impossible.

Flow layout (default behavior)

Normal flow is how elements lay out without special positioning.

Characteristics:

  • Blocks stack vertically
  • Inline content wraps horizontally
  • Margins collapse vertically

Margin collapsing:

  • Adjacent vertical margins may merge
  • Does not apply to flex/grid containers

Many “mysterious” spacing bugs are margin-collapsing effects.

Sizing units (relative vs absolute)

CSS supports multiple unit systems.

Absolute:

  • px (not truly physical pixels)

Relative:

  • % (relative to containing block)
  • em (relative to font size of element)
  • rem (relative to root font size)
  • vw, vh (viewport-relative)

Design principle:

  • Prefer relative units for scalable layouts.
  • Use rem for consistent sizing.

Colors, backgrounds, and borders

CSS supports:

  • Named colors
  • Hex, RGB, HSL
  • Transparency via alpha channels

Backgrounds:

  • Can be layered
  • Can be images or gradients
  • Controlled via background-size, position, repeat

Borders:

  • Part of the box model
  • Affect layout unless box-sizing is adjusted

Text and typography

Typography properties strongly affect readability.

Key properties:

  • font-family
  • font-size
  • line-height
  • font-weight
  • letter-spacing

Best practice:

  • Set base typography on the root (html or body)
  • Let inheritance propagate styles naturally

Stacking context and z-index (often misunderstood)

Stacking contexts define painting order.

Created by:

  • Positioned elements with z-index
  • Elements with opacity < 1
  • Transforms, filters, etc.

Rules:

  • z-index only works within the same stacking context
  • Higher z-index does not escape its context

Most z-index bugs are stacking-context bugs.

Transitions and animations

CSS can animate property changes declaratively.

Transitions:

  • Animate between states
  • Triggered by property changes

Animations:

  • Keyframe-based
  • Run independently once started

Performance note:

  • Transform and opacity animations are cheapest
  • Layout-affecting animations cause jank

CSS and performance

CSS affects performance through:

  • Selector complexity
  • Layout invalidation
  • Paint cost
  • Compositing behavior

Guidelines:

  • Avoid deeply nested selectors
  • Minimize layout-triggering changes
  • Prefer transform-based animations

CSS is part of the rendering pipeline, not just decoration.

Common CSS failure modes

  • Fighting the cascade instead of designing with it
  • Over-specific selectors
  • Layout built with hacks instead of proper layout systems
  • Excessive z-index escalation
  • Using CSS to encode application logic

Mental checklist for CSS

  • Does this rule need high specificity?
  • Is this layout one-dimensional or two-dimensional?
  • Am I triggering layout or just compositing?
  • Is this structure robust to content changes?
  • Can inheritance do this for me?