Course outline
Full-Stack course / Tools and the web

Tool tiles that respond to their container

Lab

How to fetch and submit this exercise

Once: install the tool and connect your account.

curl -fsSL https://gonomicon.com/install.sh | sh
gonomicon login

Each exercise: download it, edit the file named in the instructions, then submit.

gonomicon fetch fs-week-1/06-04-tool-deck-container-rules
cd 06-04-tool-deck-container-rules
gonomicon submit

The runner depends on the exercise: JavaScript/TypeScript/React labs run with Vitest, Python labs with pytest, and config-file labs (Docker, CI, Terraform, Nginx) are checked by parsing your file. gonomicon test runs the visible checks on your computer first; submitting also runs the hidden checks on our server.

Goal

Make each tool tile stay stacked in a narrow panel but switch to a two-column layout once its own panel is wide enough, give the tile that contains a badge a distinctly colored border, and style the tile's heading with a nested rule.

Example

A container query only works once something has been marked a container — mark the deck, not the tile, since the tile is what you're sizing against:

.tool-deck {
  container-type: inline-size;
}

@container (min-width: 36rem) {
  .tool-deck__tool {
    display: grid;
    grid-template-columns: 8rem 1fr;
  }
}

Nesting keeps a tile's own rules together, including a :has() rule that reacts to what's inside it:

.tool-deck__tool {
  border-left: 4px solid #d7dce1;

  & h2 {
    margin: 0;
  }

  &:has(.tool-deck__badge) {
    border-left-color: #7a4a00;
  }
}

Rules

  • Edit only styles.css. index.html is already correct and must not change — it has one .tool-deck containing two .tool-deck__tool elements, and only the first one contains a .tool-deck__badge.
  • Declare --tool-accent on :root, and read it with var(--tool-accent) somewhere inside a .tool-deck__tool (or nested) declaration — for example, the heading's color.
  • Put container-type: inline-size on .tool-deck, not on .tool-deck__tool. A container query reads the size of its nearest ancestor that's been marked a container — if the tile marks itself, there's no ancestor left to measure.
  • Inside the .tool-deck__tool rule, nest & h2 { ... } to style the tile's heading, and nest &:has(.tool-deck__badge) { ... } to give only the tile that contains a badge a border-left-color different from the plain #d7dce1 every tile starts with. Double-check the selector actually targets .tool-deck__badge — a :has() that doesn't match anything changes nothing.
  • Size the tile's text with clamp(min, preferred, max), where min is smaller than max and the preferred value includes a vw unit.
  • Add @container (min-width: 36rem) { .tool-deck__tool { ... } } that switches the tile from its default stacked layout to a two-column one (display: grid with at least two column tracks) once the deck is at least that wide. Use @container, not a viewport @media query — this needs to respond to the panel's own width, not the whole screen.

What you'll practice

Marking a container and writing a container query that targets it, nesting a nested-& rule and a :has() rule inside one selector, and sizing text with clamp().

Run it

gonomicon fetch fs-week-1/06-04-tool-deck-container-rules
cd 06-04-tool-deck-container-rules
gonomicon test
gonomicon submit

Hints

  1. Put container-type: inline-size on .tool-deck (the panel), not on .tool-deck__tool (the tile) — a container query can only read the size of an ancestor that's been marked as a container.
  2. Nest & h2 { ... } and &:has(.tool-deck__badge) { ... } inside the .tool-deck__tool rule. :has() only needs to change something checkable, like border-left-color — give the badged tile a different color than the plain #d7dce1 border every tile starts with.
  3. .tool-deck__tool { container query goes outside... } @container (min-width: 36rem) { .tool-deck__tool { display: grid; grid-template-columns: 8rem 1fr; gap: 1rem; } } switches the tile from stacked to two columns once its panel is wide enough — and font-size: clamp(1rem, 1.5vw, 1.25rem); keeps the tile's text fluid between a floor and a ceiling.