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

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:

<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:

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:

> 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. 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

Related