# Exercise: The Festival Lineup

Lay out the Summer Sound festival's home page with flexbox, a nav bar with the logo left and the links right, a welcome message centered both ways and a row of headliner cards that wraps to fit any screen, and let the tests check every part.

Journeyman · CSS · Updated October 30, 2026

Summer Sound is a made-up three-day music festival in a riverside park, and its tickets go on sale soon. The home page is written, and its colors and fonts are chosen, but nothing is laid out: the menu is a bulleted list, the welcome message hugs the top of the screen, and the six headliner cards are stacked in a long column. Your job is to turn it into a page people want to scroll, using only flexbox: a real nav bar, a welcome message in the middle of the screen, and a lineup that shows three cards across on a laptop and one on a phone. Tests check each part as you go.

Everything you need is in this chapter's lessons, and the whole page comes ready-made, so all of your work is in the stylesheet.

## 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. Then open the folder in VS Code.

The folder holds:

- `index.html`: the festival's home page, ready to use. You don't need to change it.
- `styles.css`: the colors, fonts and card looks, with six comments marked **STEP** where your layout rules go. For you to finish.
- `page.test.js` and `package.json`: the tests that check your layout. You don't need to change these.

## What to do

Each step has a comment in `styles.css`, and your rules go under it. The page's parts have these classes:

```html
<header class="site-header">
  <a class="logo" href="index.html">Summer Sound</a>
  <nav class="site-nav" aria-label="Main">
    <ul class="nav-links">
      <li><a href="lineup.html">Lineup</a></li>
      <!-- three more links -->
    </ul>
  </nav>
</header>
```

and further down, `<section class="hero">` holds the heading, the dates and a **Get tickets** button, and `<ul class="headliners">` holds six `<li class="card">` cards. Each card has the band's name, its genre, a few sentences, a `<ul class="tags">` list and a `<p class="set-time">`.

1. **The nav bar.** Make the header a flex container, with the logo and the menu centered on each other across the row.
2. **Logo left, links right.** Push the menu to the far right with an auto margin, and put the links side by side with a `gap`.
3. **The hero.** Stack its heading, dates and button in a column, centered up and down and left to right, in a hero at least `60vh` tall.
4. **The headliner row.** Let the cards wrap onto a new line when they run out of room, with a `gap` between them.
5. **Cards that share each line.** Give every card `flex: 1 1 15rem`.
6. **Card bottoms and tags.** Make each card a flex column with its set time pushed to the bottom, so the times line up across a row of cards. Make each tag list a row that wraps, with a `gap`.

Keep the page in its HTML order: no `order` and no reversed directions.

## Check your work

Right-click `index.html` and choose **Open with Live Server** to see the page; it reloads every time you save.

Then check it with the tests. Open a terminal in VS Code (**Terminal > New Terminal**) and run `npm install` once, to download what the tests need. After that, run the tests whenever you like:

```bash
npm test
```

At first 6 of the 8 tests fail: that's expected. The other two check that the HTML is unchanged and that nothing changes the page's order, and they should stay green. Each step you finish turns its test green. A failing test's message says what it found and where to look, for example *.site-nav has margin-left: 0. An auto margin on the left of the menu takes all the leftover space, and pushes the menu to the right.*

The tests read your rules; they can't see the page. So look at it too: the README's **Look at it** list says what to check by eye, from the cards on a phone to the order the Tab key follows.

## Hints

- **Container or item?** Most flexbox properties go on the parent: `display`, `flex-direction`, `justify-content`, `align-items`, `flex-wrap` and `gap`. The `flex` shorthand, `align-self` and auto margins go on the child. *Flexbox: Lining Things Up in a Row or a Column* shows which is which.
- **Which item gets the auto margin?** It's the header's direct child that should move. Look at the HTML above: is that the `<nav>` or the `<ul>` inside it? *Flexbox Alignment: justify-content and align-items* has a table of what each auto margin pushes.
- **Say the axes out loud.** The hero runs top to bottom, so its main axis is vertical. Which property works along the main axis, and which across it?
- **Nothing moves up and down?** A container is only as tall as its content until it has a height of its own. That's what the hero's `60vh` is for.
- **Cards that won't wrap** usually mean the row is missing `flex-wrap`, so every card squeezes onto one line. *Flexbox Wrapping and gap* shows the card row, and *Flexbox Sizing: flex-grow, flex-shrink and flex-basis* explains what each number in `flex: 1 1 15rem` does.
- **Use the flex badge.** Inspect the page and click the **flex** badge beside a container in the Elements panel: the overlay outlines its items and shades its gaps.

## When you're done

Every test is green, and `npm test` prints:

```text
> test
> node --test

✔ the page still links styles.css, and its HTML is unchanged (6.3699ms)
✔ 1) the header is a flex row, with the logo and the menu centered on each other (25.3816ms)
✔ 2) the menu is pushed to the right with an auto margin, and its links sit in a row with a gap (3.6446ms)
✔ 3) the hero is a column, centered both ways, at least 60vh tall (1.6068ms)
✔ 4) the headliner row wraps, with a gap between the cards (1.1124ms)
✔ 5) every card starts at 15rem and can grow and shrink: flex: 1 1 15rem (4.4313ms)
✔ 6) each card is a column with its set time at the bottom, and its tags wrap with a gap (9.4397ms)
✔ the HTML order is the reading order: no order and no reversed directions (16.119ms)
ℹ tests 8
ℹ suites 0
ℹ pass 8
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 728.6631
```

Your times will differ. On a wide window, the page shows three cards across, with every set time lined up along the bottom of its row; drag the window narrower and they drop to two, then one.

Now add a seventh headliner to `index.html`, a band of your own invention, with a few tags. Did it find its place in the lineup without a single new line of CSS? Then try `flex: 1 1 10rem` on the cards and see how many fit across.

## More practice in Flex Freight

Want more? Flex Freight's last four puzzles, *Shipping day*, mix everything in this chapter on one loading dock: [play them on the game's page](https://www.ask-codey.com/games/flex-freight/29?course=css-in-depth). Your solves count there, just as they do in the lessons.

## So what

A nav bar, a centered welcome and a wrapping row of cards are the layout of a huge share of the websites you visit, from festival pages to online shops. You built all three with a handful of flexbox lines and no fixed widths, so the same page works on a phone and on a wide screen.

## Key terms

- [Flexbox](https://www.ask-codey.com/glossary/flexbox)
- [Align items](https://www.ask-codey.com/glossary/align-items)
- [Auto margin](https://www.ask-codey.com/glossary/auto-margin)
- [Flex wrap](https://www.ask-codey.com/glossary/flex-wrap)
- [Gap](https://www.ask-codey.com/glossary/gap)
- [Flex shorthand](https://www.ask-codey.com/glossary/flex-shorthand)

## Related

- [Flexbox: Lining Things Up in a Row or a Column](https://www.ask-codey.com/lessons/css-flexbox-basics)
- [Flexbox Alignment: justify-content and align-items](https://www.ask-codey.com/lessons/css-flexbox-alignment)
- [Flexbox Sizing: flex-grow, flex-shrink and flex-basis](https://www.ask-codey.com/lessons/css-flexbox-sizing)
- [Flexbox Wrapping and gap](https://www.ask-codey.com/lessons/css-flexbox-wrapping)

Source: https://www.ask-codey.com/lessons/exercise-css-festival-lineup
