DevPath · Learn to code ESPTEN

Modern CSS, accessibility and architecture

Modern CSS: clamp(), aspect-ratio, :has() and more

Math functions: clamp(), min(), max()

Modern CSS ships tools that used to need juggling (or JavaScript). Let's start with the ones you'll reach for the most.

clamp(min, ideal, max) produces a fluid value that grows with the screen but never drops below the minimum nor exceeds the maximum. Think of a bouncer with two limits. It is the modern way to do responsive typography and spacing without filling everything with media queries:

h1 {
  /* never less than 1.5rem, nor more than 3rem; grows with the viewport width */
  font-size: clamp(1.5rem, 4vw, 3rem);
}

Ratios with aspect-ratio

aspect-ratio sets the width/height ratio of a box without padding tricks:

.video {
  width: 100%;
  aspect-ratio: 16 / 9; /* the height is computed on its own */
}

The :has() selector — the "parent" that was missing

For years you begged for a "parent selector" and the answer was always the same: it doesn't exist. Well, now it does, and it's called :has().

:has() selects an element based on its content or its siblings. It is the first selector that looks "downward", something that seemed impossible:

/* a card that contains an image gets a different layout */
.card:has(img) {
  display: grid;
  grid-template-columns: auto 1fr;
}

/* a label whose input is invalid is painted red */
label:has(+ input:invalid) {
  color: #b91c1c;
}

Container queries: responsive by container

Media queries look at the viewport; container queries (@container) react to the size of the parent container. This way the same component adapts wherever it is:

.panel { container-type: inline-size; }

@container (min-width: 400px) {
  .card { flex-direction: row; }
}

Native nesting

CSS already allows nesting rules like in Sass, without compiling:

.menu {
  background: #fff;

  & a {
    color: var(--primary-color);

    &:hover { text-decoration: underline; }
  }
}

The & represents the parent selector. Nesting brings the style closer to the structure of the component and reduces repetition. Just don't get carried away nesting six levels deep, or you'll recreate the exact mess we came here to avoid.

Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Custom properties: CSS variablesAccessibility and CSS architecture →