🚀 New batches open: Advanced Excel • Power BI • SQL • AI for Analytics — Book a free demo

Day 9 — Layout with Flexbox

Everything people used to do with tables and floats, done properly in about six properties.

One line changes everything

<style>
  .row { display: flex; gap: 12px; }
  .row div { background:#E8EEF8; padding:14px; }
</style>

<div class="row">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

Those are divs, which are normally block elements that stack. display: flex on the parent puts its children in a row.

Flex properties live on the container You set display: flex on the parent and it controls the children. Beginners try to put justify-content on the item and wonder why nothing happens.

gap - the property that killed margin hacks

gap puts space between the items and nowhere else - no leftover margin on the last one to strip off.

<style>
  .row { display:flex; gap:24px; background:#F6F8FC; padding:12px; }
  .row div { background:#1D3B73; color:#fff; padding:14px; }
</style>

<div class="row">
  <div>A</div><div>B</div><div>C</div>
</div>

justify-content - along the row

<style>
  .row { display:flex; background:#F6F8FC; margin-bottom:10px; padding:8px; }
  .row div { background:#1D3B73; color:#fff; padding:10px 14px; }
  .start   { justify-content: flex-start; }
  .center  { justify-content: center; }
  .end     { justify-content: flex-end; }
  .between { justify-content: space-between; }
  .around  { justify-content: space-around; }
</style>

<div class="row start"><div>flex-start</div><div>B</div></div>
<div class="row center"><div>center</div><div>B</div></div>
<div class="row end"><div>flex-end</div><div>B</div></div>
<div class="row between"><div>space-between</div><div>B</div></div>
<div class="row around"><div>space-around</div><div>B</div></div>

space-between is how every navigation bar on the web puts the logo left and the menu right.

align-items - across the row

<style>
  .row { display:flex; gap:10px; background:#F6F8FC;
         height:110px; margin-bottom:10px; padding:8px; }
  .row div { background:#1D3B73; color:#fff; padding:10px; }
  .stretch { align-items: stretch; }
  .top     { align-items: flex-start; }
  .middle  { align-items: center; }
  .bottom  { align-items: flex-end; }
</style>

<div class="row stretch"><div>stretch (default)</div><div>B</div></div>
<div class="row middle"><div>center</div><div>B</div></div>
<div class="row bottom"><div>flex-end</div><div>B</div></div>
The two axes justify-content works along the direction the items flow. align-items works across it. Add flex-direction: column and the two swap over, which catches everybody the first time.

A navigation bar

<style>
  *, *::before, *::after { box-sizing:border-box; }
  body { font-family:system-ui, sans-serif; margin:0; }
  .nav {
    display:flex; align-items:center; justify-content:space-between;
    gap:16px; padding:14px 20px; background:#0A1A3D; color:#fff;
  }
  .nav .logo { font-weight:800; letter-spacing:.5px; }
  .nav ul { display:flex; gap:18px; list-style:none; margin:0; padding:0; }
  .nav a { color:#E8EEF8; text-decoration:none; }
  .nav a:hover { color:#F0B429; }
</style>

<header class="nav">
  <div class="logo">DAI ACADEMY</div>
  <nav>
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/courses">Courses</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </nav>
</header>

Two flex containers nested: the header spreads logo and nav apart, and the ul lays the links out in a row. That is a real site header in twelve lines of CSS.

flex-wrap - onto the next line

Without wrapping, flex squashes everything to fit. With it, items drop to a new line instead.

<style>
  .cards { display:flex; flex-wrap:wrap; gap:12px; }
  .cards .card {
    flex: 1 1 180px;
    background:#fff; border:1px solid #D3DDEC; border-radius:10px;
    padding:14px; box-sizing:border-box;
  }
  body { background:#F6F8FC; font-family:system-ui, sans-serif; }
</style>

<div class="cards">
  <div class="card"><b>Excel</b><p>6 weeks</p></div>
  <div class="card"><b>Power BI</b><p>5 weeks</p></div>
  <div class="card"><b>SQL</b><p>4 weeks</p></div>
  <div class="card"><b>Python</b><p>8 weeks</p></div>
</div>
flex: 1 1 180px, decoded grow 1 - share out any spare space.
shrink 1 - give space back if there is not enough.
basis 180px - start from 180px wide.
Together: "aim for 180px, stretch to fill the row, and wrap when you cannot fit". That one line is a responsive card grid, with no media query at all. Drag the preview narrower and watch it rearrange.

Sidebar and content

<style>
  *, *::before, *::after { box-sizing:border-box; }
  body { font-family:system-ui, sans-serif; }
  .layout { display:flex; gap:20px; flex-wrap:wrap; }
  .side { flex: 0 0 180px; background:#E8EEF8; padding:14px; }
  .body { flex: 1 1 300px; background:#F6F8FC; padding:14px; }
</style>

<div class="layout">
  <aside class="side">
    <b>Contents</b>
    <p>Fixed 180px</p>
  </aside>
  <main class="body">
    <h2>Main content</h2>
    <p>Takes whatever is left, and drops below the sidebar
       when the screen gets narrow.</p>
  </main>
</div>

flex: 0 0 180px is "do not grow, do not shrink, be 180px". flex: 1 1 300px is "take the rest, but wrap below 300".

Flexbox or Grid? Flexbox lays things out in one direction - a row or a column. CSS Grid does two at once, rows and columns together. For navigation bars, toolbars, card rows and sidebars - which is most of what you will build - Flexbox is the right tool and it is what interviewers ask about first.

Try these yourself

  1. Build a navigation bar with the logo on the left and three links on the right.
  2. Make a row of four cards that wrap onto a second line when the space runs out.
  3. Centre a box both horizontally and vertically inside a 300px tall container.
  4. Build a sidebar and content layout where the sidebar is a fixed 200px.
  5. Explain what flex: 1 1 200px means, one number at a time.