Exercise: Bike Cards That Fit Anywhere
Make one Spoke & Chain bike card fit three kinds of spots, a wide feature, a catalog column and a narrow sidebar, with named containers, @container rules and a fluid title, and let the tests check each part.
Journeyman · CSS · Updated
Spoke & Chain's catalog page shows the same bike card in three kinds of spots: a wide "Bike of the month" spot at the top, a catalog of three columns, and a narrow "Staff pick" sidebar. Someone made the cards side by side with a media query, and on a laptop it went wrong: every card went side by side, so the bikes in the narrow catalog columns and the sidebar are crushed into slivers. Your job is to make the card fit whatever space it's given, with container queries, and to give each card's title a size that grows with its card. Tests check each part as you go.
Before you start
You need Node.js to run the tests. Setup: VS Code, a Browser and Node.js installs it, along with VS Code and Live Server. Everything else, the page and its pictures included, comes with the exercise code.
Get the exercise code
In the Exercise box beside the lesson, choose Get the starter on GitHub to open its GitHub repository. Click Code, then Download ZIP, and unzip it into your css-in-depth folder.
The folder holds:
index.html: the catalog page, with five bike cards. It's ready, and you don't change it.styles.css: the colors, the fonts, the page layout and the card's stacked look are ready. Your work goes below the line that says Yours: cards that fit their space, and the media query marked The problem is yours to delete.images/: a picture of each bike.page.test.jsandpackage.json: the tests. You don't need to change these.
Open the folder in VS Code, right-click index.html and choose Open with Live Server. Make the window wide, and look at the sidebar's card.
What to do
Every card sits in its own spot, a <div class="card-spot">, and every card has the same classes:
<div class="card-spot">
<article class="bike-card">
<img class="bike-card-photo" src="images/gravel-fox.svg" alt="The Gravel Fox, an orange gravel bike with wide tires and drop handlebars">
<div class="bike-card-body">
<h3 class="bike-card-title">Gravel Fox</h3>
<p class="bike-card-type">Gravel bike</p>
<p class="bike-card-price">$1,180</p>
<p class="bike-card-blurb">Paved road to dirt trail and back again: wide tires, a comfortable fit and mounts for three water bottles.</p>
<a class="bike-card-button" href="#gravel-fox">See the Gravel Fox</a>
</div>
</article>
</div>
The comment at the top of styles.css lists the work, and the README says the same:
- Make every spot a container: each
.card-spotmeasures its width, and is namedbike-spot. - Delete the problem: the media query that makes every card side by side on a wide screen.
- Side by side when there's room: an
@container bike-spotrule that gives the card two columns once its spot is wide enough, somewhere from 26rem to 34rem. Look at the page to decide where. - A look for the wide spot: a second, wider
@container bike-spotrule, at least 8rem wider and after the first, for the bike of the month. What it changes is up to you. - A fluid title:
.bike-card-titlegets a font size withclamp(), its limits in rem and a preferred size that mixes rem andcqi.
Leave the page layout's media queries alone: the sidebar moving beside the main area is about the screen, and a media query is the right tool for that.
Check your work
In VS Code, open a terminal (Terminal > New Terminal). Run npm install once, to download what the tests need, then run the tests as often as you like:
npm install
npm test
At first seven of the eight tests fail. That's expected: only the first one passes, because it checks the page that's already there. Each part you add turns its test green. A failing test's message says what it found and what to fix, for example The rule for .bike-card sits inside @media (min-width: 60rem), so it changes the cards by the screen's width.
The tests read your rules, but they can't measure a container: the browser they use doesn't lay out pages. The README's How it should look checklist covers that part. Go through it in device mode at 375, 768 and 1280 pixels wide.
Hints
- Measure the spot, change the card. A container query styles what's inside the container, never the container itself. Container Queries: Components That Fit Their Space shows why each card sits in a wrapper.
- Where does the card start to look empty? Make the window narrow, then widen it slowly while you watch the bike of the month. The width of its spot when there's room for a photo beside the words is your first breakpoint. Hover a
.card-spotin the Elements panel, and the page shows its width. - Two rules, both matching? In a wide spot both of your
@containerrules apply, and the later one wins where they disagree. Small spots first, then more room. - A title that grows with its card.
cqiis 1% of the container's width, the wayvwis 1% of the window's. Fluid Type and Spacing with clamp() shows how to pick the minimum and the maximum, and why the preferred size keeps a rem. - Something changed in the wrong spot? Inspect the card and look at the Styles pane: it shows each
@containerrule that's applying, above the declarations inside it.
When you're done
Every test is green, and the end of the test run says:
ℹ tests 8
ℹ pass 8
ℹ fail 0
On a phone, every card is stacked. On a tablet, the bike of the month and the staff pick, which now runs the full width below the catalog, sit side by side, while the catalog's narrower cards stay stacked. On a laptop, the bike of the month has its wide-spot look, and the sidebar's card is stacked and readable. One card, one set of rules, and it fits every spot. Now ask yourself: if the shop added a fourth spot tomorrow, say a footer with two cards side by side, how much CSS would you need to add for the cards? If the answer is "none", your container queries are doing their job.
So what
The card you built is a component: a piece of a page that works wherever it's placed. That's how teams build big sites, from shops to streaming services: they design a card, a menu or a player once, and container queries let it fit a sidebar, a grid or a full-width banner without a new rule for every page.
What Module 5 unlocks
That's Module 4 done: your pages work from a 320-pixel phone to a wide screen, with breakpoints where the content needs them, fluid sizes, pictures that fit and components that adapt to their space. The Module 4 project, Your Travel Bucket List, puts all of it into a site about six places you dream of going, with their photos, why each is on the list, the best time to go and what to pack. You'll open it on your own phone to check it.
A page that fits every screen can still look a little off, and it's often hard to say why. Module 5 is design. It shows why some pages look professional and others don't, and the small rules behind the difference: spacing, alignment, a type scale. You'll choose fonts and colors that read well for everyone, with contrast you can measure. You'll theme a whole site, light and dark, from a handful of variables, so changing one color changes it everywhere. And you'll add motion that helps the reader, a button that responds or a card that eases into view, and calms down for people who asked their device for less motion.