Web Foundations Lesson 4 of 7

CSS box model and flexbox

35 min, 6 exercises

Builds on lessons 1 to 3. Start at lesson 1

Learn

The four box layers

Here is the secret that makes CSS layout click: every element is a rectangle. Even a single word. Each box has four layers, from the inside out:

  1. content: the text or image itself
  2. padding: space inside the box, between the content and the border
  3. border: a line around the padding
  4. margin: space outside the border, pushing other boxes away
.card {
  padding: 16px;
  border: 2px solid black;
  margin: 10px;
}

border takes three values at once: thickness, style (solid, dashed, dotted) and colour. If you are ever confused about why something is the size it is, add a bright border to it. Professional developers do this daily and will deny it.

Learn

Laying out with flexbox

By default, block elements like <div> stack on top of each other. To put them side by side, make their parent a flex container:

.row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

Now every direct child of .row sits in one horizontal line. The important bit: you put display: flex on the container, not on the children. The container is in charge of the layout.

justify-content decides how the children spread along the row:

  • flex-start: bunched at the start (the default)
  • center: bunched in the middle
  • space-between: first one at the start, last one at the end, even gaps between

gap adds space between the children without messing with their margins. align-items: center lines them up vertically in the middle, which is the famous "how do I centre a div" answer.

Try

Run it: a row of cards

Press Run and the page appears in the preview under the editor. Change some text or a colour and run it again.

example.html to run
<style>
  .row {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 12px;
    background-color: #eeeeee;
    padding: 10px;
  }
  .card {
    padding: 16px;
    border: 2px solid teal;
    margin: 4px;
    background-color: white;
  }
</style>
<div class="row">
  <div class="card">One</div>
  <div class="card">Two</div>
  <div class="card">Three</div>
</div>

Practice

Pad the box

Give .box a padding of 20px, a border of 2px solid black, and a margin of 10px.

exercise_1.html to run
<style>
  .box {
    background-color: lightblue;
  }
</style>
<div class="box">I need some breathing room.</div>

Practice

Make a flex row

Make .row a flex container so the three items sit side by side, with justify-content set to space-between.

exercise_2.html to run
<style>
  .row {
    border: 1px solid gray;
  }
  .item {
    padding: 10px;
    background-color: orange;
  }
</style>
<div class="row">
  <div class="item">A</div>
  <div class="item">B</div>
  <div class="item">C</div>
</div>

Practice

Centre a button in a bar

The .bar is 120px tall. Use flexbox on the bar so the Play button sits in the exact middle, both across and down.

exercise_3.html to run
<style>
  .bar {
    height: 120px;
    background-color: #dfe8ff;
  }
</style>
<div class="bar">
  <button id="play">Play</button>
</div>

Practice

A streamer profile header

Style the header so it looks like a profile bar:

  • .profile is a flex row with 16px of padding and a 1px solid border; the avatar, the name and the Follow button are all centred top to bottom
  • .who (the avatar and the name) sits at the left edge and the button at the right edge
  • inside .who, the avatar and the name sit side by side with a 12px gap
exercise_4.html to run
<style>
</style>
<header class="profile">
  <div class="who">
    <img src="/assets/noodle/coding.svg" alt="Noodle typing on a laptop" width="64">
    <h2>NoodleCodes</h2>
  </div>
  <button>Follow</button>
</header>

Practice

Tags that run off the edge

A flex row stays on one line, whatever happens. When the items do not fit, they shrink as far as they can and then spill out of the box. flex-wrap: wrap lets them move onto a new line instead, and gap then spaces the lines as well as the items.

The genre tags below stick out of their 240px box. Make .tags wrap, with an 8px gap.

exercise_5.html to run
<style>
  .tags {
    display: flex;
    width: 240px;
    padding: 8px;
    border: 1px solid #1d2b6b;
  }
  .tag {
    padding: 4px 10px;
    background-color: #dfe8ff;
    white-space: nowrap;
  }
</style>
<div class="tags">
  <span class="tag">Indie pop</span>
  <span class="tag">Lo-fi</span>
  <span class="tag">Drum and bass</span>
  <span class="tag">Jazz</span>
  <span class="tag">Film scores</span>
  <span class="tag">Grime</span>
  <span class="tag">Synthwave</span>
  <span class="tag">Folk</span>
</div>

Your turn

A wall of album covers

Lay out the album wall:

  • every .cover is 100px wide, with 8px of padding and a 2px solid border
  • .wall is a flex container: the covers wrap onto as many lines as they need, with a 12px gap between covers and between lines
  • the covers on each line sit in the middle of the wall, with the same space left and right

On your own. Hints open after your first check.

exercise_6.html to run
<div class="wall">
  <div class="cover">Neon Rain</div>
  <div class="cover">Late Bus</div>
  <div class="cover">Stone Road</div>
  <div class="cover">Paper Planes</div>
  <div class="cover">Night Swim</div>
  <div class="cover">Low Tide</div>
  <div class="cover">Glass Garden</div>
  <div class="cover">Static Hearts</div>
  <div class="cover">Kite Song</div>
  <div class="cover">Rain Again</div>
</div>
<style>
</style>
HTML, CSS and JavaScript

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.