Skip to content

Beyond the breakpoint: how media queries actually work

What happens inside the browser when you resize a window? A look at the four-step process that turns a CSS media query into a layout change.

You're on a site, the layout looks fine, and then you drag the browser corner to make the window smaller. The sidebar disappears, the nav collapses into a hamburger menu, three columns become one.

We write @media (max-width: 768px) and the layout adjusts. Most developers know what media queries do. Fewer know what the browser is actually doing in the milliseconds between the resize and the repaint.

There are four steps: parse, trigger, recalculate, paint. Here's what each one does.

How browsers parse media query rules

Before anything changes on screen, the browser has to understand what you wrote. It doesn't read your CSS file line by line the way you'd read a document. It builds a structure called the CSS Object Model (CSSOM), a full map of every style rule before any of them get applied.

When it hits a media query like this:

@media (max-width: 768px) {
  .sidebar {
    display: none;
  }
}

it doesn't apply the styles immediately. It flags the block as conditional and stores it in a structure linked to its condition, max-width: 768px in this case. The browser knows the rule exists and what it contains, but none of it is active yet. It's waiting for the condition to become true.

What happens when the viewport changes

Resizing the window changes the viewport dimensions, and the browser re-evaluates its stored media query conditions as part of the same style and layout recalculation that the resize triggers.

When that happens, the browser checks the new viewport dimensions against every stored media query condition:

  • Does current_width <= 768?
  • Is orientation === 'portrait'?
  • Does min-height >= 600?

Each check is a boolean. Scripts listening via matchMedia only get notified when a condition's truth value flips, a condition that was already true and stays true fires no new change event. If your window was 800px and you resize to 750px, max-width: 768px just flipped from false to true, that's the trigger.

Once a condition flips, the browser moves to the next step.

How new styles get applied

Activating a media query doesn't replace the old styles outright. It adds new rules into the same cascade that was already running, the one that resolves specificity, inheritance, and source order.

.header {
  background-color: blue;
  padding: 20px;
}

@media (max-width: 768px) {
  .header {
    background-color: red;
    padding: 10px;
  }
}

When the media query activates, the browser recalculates styles for every affected element rather than discarding the original rule. Here, both background-color declarations have identical specificity, so the one that comes later in source order wins: red. An !important declaration inside a media query still gets the priority !important always gets. The cascade doesn't make an exception for media queries.

Layout, paint, and why it's fast

Once the browser knows the final styles, it has to make the change visible. That happens in two phases.

Layout, also called reflow, runs when the changed properties affect geometry: width, height, display, font size. The browser recalculates where every affected element sits on the page.

Paint runs after layout. The browser draws the updated pixels for whatever changed.

Reflow costs more than paint, since geometry changes can cascade to other elements, but on an ordinary page the whole sequence for a media query change is fast enough to be imperceptible, the exact duration depends on page complexity and how many elements the layout affects. Browser engines are built specifically to make this fast, which is why a well-built responsive layout transitions smoothly instead of visibly redrawing.

Media queries are rarely a performance bottleneck. Large images and heavy JavaScript cost far more than a resize recalculation ever will.

That holds for a breakpoint quietly flipping on an otherwise idle page. It stops holding the moment JavaScript gets involved in the resize itself. A handler that reads a layout property like offsetWidth and then writes a style back, repeated on every pixel the user drags, is a textbook case of layout thrashing. That slowdown comes from the handler, not from the media query sitting in your CSS.

FAQ

What happens when multiple media queries match at the same time?

All of them stay active. The browser doesn't pick one, it applies every matching rule and lets the existing cascade rules decide the final styles.

Do media queries slow down a site?

Not meaningfully. Parsing and storing the rules happens once, when the CSS loads. Checking conditions and recalculating styles is fast, usually a few milliseconds. Image weight and JavaScript execution are far more likely culprits if a site feels slow.

Why do some media query changes feel instant while others feel sluggish?

It depends on what's changing. A color change only triggers paint. A width or display change triggers layout first, which costs more, especially in a page with many nested elements.

Can you have too many media queries?

The browser handles hundreds without trouble. The cost shows up in your codebase instead: too many breakpoints usually means the design itself needs fewer decision points, not that the CSS needs optimizing. Most responsive designs hold up fine with three or four well-chosen breakpoints.

Do media queries work the same way in every browser?

The parse-trigger-recalculate-paint sequence is the same across modern browsers. The differences show up at the edges, timing quirks and how specific edge cases get handled, not in the core model.

Should I use container queries instead?

For page-level layout, media queries are still the right tool. They respond to the viewport, and a whole page restructuring at a given width is exactly what they're for. But a lot of what teams now reach for media queries to do, making one component adapt to the space it's actually given, fits container queries better. A sidebar widget and a full-width hero can't share a viewport breakpoint that makes sense for both, since they need different things at the same window width. Container queries respond to the container's size instead, which is the gap they close. It's a different enough mechanism to deserve its own post rather than a footnote here.

Wrapping up

@media (max-width: 768px) looks like one line of CSS, but it triggers a four-step sequence: the browser parses and stores the conditional rule, listens for the viewport condition to flip, recalculates styles through the same cascade rules that govern everything else, then reflows and repaints to make the change visible.

None of it is magic. It's a resize listener, a condition check, a cascade recalculation, and a repaint, running fast enough that it looks instant. Knowing that sequence is the difference between copying @media syntax from a tutorial and knowing why it behaves the way it does when your layout doesn't turn out the way you expected.