Kodokon kodokon.com

Container queries and CSS nesting

Make your components responsive to their container rather than the viewport, and structure your stylesheets with native nesting.

10 min · 3 questions

Open this lesson in Kodokon

Media queries measure the viewport: a card displayed both in a narrow sidebar and in a main grid cannot adapt correctly with them, because the same screen width corresponds to two different contexts. Container queries resolve this decoupling: the component queries the size of its container. Prerequisite: explicitly designate a container with container-type (inline-size to measure only the horizontal axis, the common case), optionally named via container-name.

CSS
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

@container sidebar (min-width: 400px) {
  .widget {
    display: grid;
    grid-template-columns: 80px 1fr;
    gap: 12px;
  }
}
A widget that adapts to its column, not the screen

Container units complete the picture: 1cqi equals 1% of the inline size of the queried container (cqw, cqh, cqb, cqmin, cqmax also exist). Combined with clamp(), they produce fluid typography per component: the same card gets a title proportioned to its column, wherever it is placed.

CSS
.card-slot {
  container-type: inline-size;
}

.card h2 {
  font-size: clamp(1rem, 5cqi, 1.75rem);
}

@container (max-width: 300px) {
  .card .meta {
    display: none;
  }
}
cqi units and a query without a container name

Native nesting finally brings nesting without a preprocessor. The & selector references the parent context; media queries and @container nest directly inside a rule. A crucial difference from Sass: the nested parent is treated as if wrapped in :is(). Two consequences: the parent's specificity is that of the strongest of its selectors if it is a list, and & .child does not perform string concatenation - the Sass &__element pattern for generating BEM names does not exist natively.

CSS
.menu {
  display: flex;
  gap: 8px;

  & > li {
    list-style: none;

    &:hover {
      background: #f3f4f6;
    }
  }

  @media (min-width: 768px) {
    gap: 16px;
  }
}
Native nesting: states, descendants, and a media query

Knowledge check

Make sure you remember the key points of this lesson.

  1. Why is a container query preferable to a media query for a reusable card?
    • It is faster for the rendering engine to evaluate
    • It reacts to the size of the card's container, which is the same on any screen where the column is narrow
    • It works without declaring any CSS prerequisite
    • It can query the viewport's height in addition to its width
  2. What does 5cqi correspond to?
    • 5% of the viewport width
    • 5% of the inline size of the queried container
    • 5 times the container's font size
  3. How does native nesting differ from Sass nesting?
    • Native nesting forbids nesting media queries inside a rule
    • Native nesting treats the parent as wrapped in :is() and does not allow &__element-style concatenation
    • Native nesting requires a preprocessor to compile the & symbol
    • Native nesting limits nesting to a single level