Skip to main content
CodeOath
← All posts

HTML & CSS82 min total · 18 parts

CSS Fundamentals: The Box Model, Specificity, Positioning, and Layout

Part 15 of 18 · ~2 min

Responsive Design: Media Queries and Container Queries

The category page's sidebar-plus-grid layout needs to collapse to one column on a narrow screen, and a media query — which reads the viewport itself — is the obvious first move:

.category-page {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .category-page {
    grid-template-columns: 240px 1fr;
  }
}

This is the mobile-first convention: the small-screen styles are the baseline, and each min-width query only adds rules once the viewport clears a given width. It holds up better over time than starting from a desktop layout and subtracting with max-width queries, especially once a page has collected more than one or two breakpoints.

Media queries answer "how wide is the screen?" — and that question turns out to be the wrong one for the card itself. The exact same .card renders in three completely different widths on this one page: roughly 380px wide in the grid, exactly 220px wide in the rail, and about 300px wide in the cart drawer. A rule like this one, written to hide the description on genuinely small cards, breaks the moment it meets the rail:

@media (min-width: 350px) {
  .card__description { display: block; }
}

On a 1400px-wide monitor, that media query is true — the viewport is nowhere near 350px — so the description shows up in the rail too, where the card itself is only 220px wide, and the text overflows its box or gets crushed against the price. The viewport was wide. The card wasn't. A media query has no way to tell the difference, because it was never asking about the card in the first place.

A container query is built to ask the right question in the first place — it measures the box an element is actually sitting inside, and it never looks at the screen at all:

.rail .card,
.grid .card,
.cart-drawer .card {
  container-type: inline-size; /* register this box as something @container rules can measure */
}

@container (min-width: 350px) {
  .card__description { display: block; } /* only when THIS card's own box is at least 350px wide */
}

Now the description shows up in the roomy grid card, stays hidden in the cramped rail card, and the rule never has to know or care what the browser window is doing — which is exactly the question a genuinely reusable component needs answered, and the one it never had a way to ask before container queries existed.