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.
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>
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>
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".
Try these yourself
- Build a navigation bar with the logo on the left and three links on the right.
- Make a row of four cards that wrap onto a second line when the space runs out.
- Centre a box both horizontally and vertically inside a 300px tall container.
- Build a sidebar and content layout where the sidebar is a fixed 200px.
- Explain what flex: 1 1 200px means, one number at a time.
