Tool tiles that respond to their container
How to fetch and submit this exercise
Once: install the tool and connect your account.
curl -fsSL https://gonomicon.com/install.sh | sh
gonomicon loginEach 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 submitGoal
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.htmlis already correct and must not change — it has one.tool-deckcontaining two.tool-deck__toolelements, and only the first one contains a.tool-deck__badge. - Declare
--tool-accenton:root, and read it withvar(--tool-accent)somewhere inside a.tool-deck__tool(or nested) declaration — for example, the heading's color. - Put
container-type: inline-sizeon.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__toolrule, nest& h2 { ... }to style the tile's heading, and nest&:has(.tool-deck__badge) { ... }to give only the tile that contains a badge aborder-left-colordifferent from the plain#d7dce1every 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), whereminis smaller thanmaxand the preferred value includes avwunit. - Add
@container (min-width: 36rem) { .tool-deck__tool { ... } }that switches the tile from its default stacked layout to a two-column one (display: gridwith at least two column tracks) once the deck is at least that wide. Use@container, not a viewport@mediaquery — 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
- Put
container-type: inline-sizeon.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. - Nest
& h2 { ... }and&:has(.tool-deck__badge) { ... }inside the.tool-deck__toolrule.:has()only needs to change something checkable, likeborder-left-color— give the badged tile a different color than the plain#d7dce1border every tile starts with. .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 — andfont-size: clamp(1rem, 1.5vw, 1.25rem);keeps the tile's text fluid between a floor and a ceiling.