Exercise: A Reusable Review Card
Build Pixel Palace's reviews page with a banner in declarative shadow DOM, a review card layout written once and used four times, and star ratings from a ready-made custom element, then explain two repairs the parser made, and let the tests check it all.
Freelancer · HTML · Updated
Pixel Palace, a made-up video game store, has a reviews page that grew one copy-and-paste at a time. The owner wants every review card to share one layout, so a change to the design is one edit instead of forty, and a Game of the Month banner that looks right the moment the page arrives, with no script. While you're there, the store's old reviews from 2019 are full of sloppy HTML: the owner wants to know what the browser has been quietly fixing. Tests check every part as you go.
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 the folder where you keep this course's work. Open that folder in VS Code.
The folder holds:
index.html: the reviews page, with comments marked STEP where your work goes. For you to finish.repairs.md: two questions about the old reviews. For you to finish.star-rating.jsandreview-card.js: two ready-made scripts that define the<star-rating>and<review-card>custom elements. You don't need to change or read them.card.cssandstyle.css: ready-made stylesheets, one for the layout inside each shadow root and one for the page.covers/: a cover picture for each game.page.test.jsandpackage.json: the tests.
The folder's README.md lists every file and the exact shape of each layout.
What to do
Each review is already a <review-card>, but its pieces have no slots yet, so for now the card shows them as plain text:
<review-card>
<h3>Moon Garden</h3>
<img src="covers/moon-garden.svg" alt="Moon Garden cover: a glowing purple flower growing under a full moon" width="120" height="160">
<p>Rating: 5 out of 5 stars</p>
<p>Reviewed by MossyBoots</p>
<p>The calmest game I own. I water my space plants every night before bed, and the music is like a warm blanket.</p>
</review-card>
- Give the banner a layout of its own. Put a
<template shadowrootmode="open">inside the Game of the Month section, with the layout the README describes, and give the banner's heading, picture and paragraph their slots. - Write the review card's layout once, in a
<template id="review-card">with five named slots: cover, title, rating, reviewer and review. - Fill in the three cards. Give every piece its slot, and swap each "Rating:" paragraph for a
<star-rating>with aratingattribute and the same words inside. - Add the fourth card, Deep Sea Diner, from the text in the STEP 4 comment.
- Explain two repairs. Compare the old reviews in View Source and in the Elements panel, and answer the two questions in
repairs.md. Leave the old reviews' HTML as it is.
Check your work
Open index.html with Live Server to see the page as you go. To run the tests, open VS Code's terminal (Terminal > New Terminal) and run npm install once, then this each time you want to check:
npm test
At first most tests fail. That's expected: each step you finish turns its tests green. When a test fails, its message says what it looked for, for example In Turbo Kart Rally, the <img> isn't in a slot, so it won't show. Give it a slot attribute that matches a slot in the layout.
Hints
- A blank card is a clue. Once the template exists, a piece with no
slotattribute, or with a name the layout doesn't have, disappears from the card. Templates, Slots and Custom Elements shows how the names match up. - Look inside the shadow root. In the Elements panel, expand a card, then
#shadow-root (open), and hover each<slot>to see the piece it shows. - Two layouts, two ways. The banner's layout lives inside the banner; the cards' layout lives in one shared template. Only the banner's template gets
shadowrootmode. - Words inside the stars. The words inside a
<star-rating>show before its script loads, and a screen reader reads them, so keep them. - For the repairs, look for a
<div>inside a paragraph, words typed straight into a table, and tags that cross each other. How the Browser Parses HTML names each repair.
When you're done
Every test is green:
✔ the page keeps its skeleton and its two ready-made scripts
✔ the Game of the Month banner has a layout of its own, in declarative shadow DOM
✔ every piece of the banner fills one of its slots
✔ the review card layout is written once, in <template id="review-card">
✔ four review cards, one for each game
✔ every piece of every card lands in a slot
✔ every rating is a <star-rating> with a rating from 1 to 5 and words inside
✔ every cover has alt text, a width and a height
✔ the new sections pass the validator
✔ repairs.md describes two things the parser repaired
ℹ tests 10
ℹ pass 10
ℹ fail 0
In the browser, the banner and four cards each show a cover beside the title, with stars under the review cards' titles. Now move the rating slot above the title in your <template id="review-card"> and reload. How many places did you change, and how many cards moved?
So what
A layout written once and filled in many times is how every large site keeps hundreds of cards, buttons and badges consistent. You built one with HTML alone and two small scripts, and you can explain what the browser does with the sloppy HTML it meets along the way.
What's next
You've reached the end of the course's lessons. Two projects are left, and they're the best part.
- The Module 5 mini-capstone: Your Portfolio Page. A one-page "link in bio" portfolio: who you are (only what you choose to share), the projects you've built, each as a card made from one
<template>, a contact link, and the metadata that makes its link show a title, a description and a picture when you paste it into a chat. It passes a keyboard test, a screen-reader test and the validator, and goes online. - The final capstone: a website for a local business. This is the course's final assessment. Pick one of three made-up businesses (Sunrise Bakery, Riverside Bikes or Pawsitive Dog Walking), or a real one you know, with the owner's permission. Build at least four pages: home, about, a menu or price list in a table, a gallery, and a contact form. It brings the whole course together: semantic, accessible, valid HTML, responsive images, search and sharing metadata, and a link you can send to the owner.
- Where to go after that, if you want to. CSS in Depth teaches you to design your own look instead of using a ready-made stylesheet. JavaScript in Depth makes pages respond, and teaches you to write custom elements like
<star-rating>yourself. Each course stands on its own, so start with whichever one excites you.