CSS Flexbox is a layout system for arranging items in one direction: a row or a column. It makes everyday tasks easy that used to need hacks, such as centring something vertically, spacing navigation links evenly or making cards in a row equal height. It is supported in every modern browser and is a core skill for any front-end developer.
Flex containers and flex items
CSS Flexbox works on two levels. You add display: flex to a parent, which becomes the flex container. Its direct children automatically become flex items and line up in a row. Grandchildren are not affected unless you make their parent a flex container too.
Flexbox thinks in two axes. The main axis is the direction items flow, set by flex-direction (row by default, or column). The cross axis runs at right angles to it. Almost every flex property aligns along one of these two axes, so knowing which is which is the key to Flexbox.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A navigation bar with Flexbox</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
.nav {
display: flex;
align-items: center; /* cross axis: vertical centre */
justify-content: space-between; /* main axis: spread out */
gap: 16px;
padding: 12px 20px;
background: #102a43;
color: white;
}
.nav ul {
display: flex;
gap: 20px;
list-style: none;
margin: 0;
padding: 0;
}
.nav a { color: white; text-decoration: none; }
</style>
</head>
<body>
<nav class="nav">
<strong>Thanjavur Crafts</strong>
<ul>
<li><a href="#">Paintings</a></li>
<li><a href="#">Dolls</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</body>
</html>Container properties
| Property | Common values | What it controls |
|---|---|---|
flex-direction | row, column | The direction of the main axis |
justify-content | flex-start, center, space-between, space-evenly | Alignment and spacing along the main axis |
align-items | stretch, center, flex-start, baseline | Alignment along the cross axis |
flex-wrap | nowrap, wrap | Whether items may move onto new lines |
gap | 16px, 1rem 2rem | Space between items (not around the edges) |
The default align-items: stretch is why flex items in a row become equal height: they all stretch to the tallest one. Use gap for spacing between items instead of margins. It never adds space at the outer edges and needs no “remove the margin on the last item” fixes.
Tip: Centring anything both ways takes three lines: display: flex; justify-content: center; align-items: center; on the parent. The parent needs some height for the vertical centring to be visible.
Item properties: grow, shrink and basis
Flex items can share space flexibly. Three properties control this, usually written together with the flex shorthand:
flex-grow: how much of the leftover space an item takes.1means “take an equal share”;0means “do not grow”.flex-shrink: how much an item shrinks when there is not enough space. The default is1.flex-basis: the starting size before growing or shrinking, such as200pxorauto.
Common shorthands are flex: 1 (grow equally from a zero basis, so items end up the same width) and flex: 1 1 250px (start at 250px, then grow or shrink). An individual item can break alignment with align-self, and margin-inline-start: auto pushes an item to the far end of a row.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Wrapping cards that share space</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; padding: 20px; }
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 220px; /* at least about 220px, grow to fill */
padding: 16px;
border: 1px solid #d0d7de;
border-radius: 10px;
display: flex;
flex-direction: column;
}
.card button {
margin-block-start: auto; /* pushes button to the bottom */
padding: 8px;
font: inherit;
}
</style>
</head>
<body>
<div class="cards">
<article class="card"><h3>Ooty</h3><p>Tea gardens and a toy train.</p><button>Explore</button></article>
<article class="card"><h3>Coorg</h3><p>Coffee estates, waterfalls and misty hills with long walking trails.</p><button>Explore</button></article>
<article class="card"><h3>Gokarna</h3><p>Quiet beaches.</p><button>Explore</button></article>
</div>
</body>
</html>Resize the preview: the cards wrap onto new lines when there is no room for 220px each, with no media query needed. Each card is also a column flex container, so margin-block-start: auto pushes every button to the bottom and they line up neatly even when descriptions differ in length.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Perfect centring and push-to-end</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
.hero {
min-height: 60vh;
display: flex;
justify-content: center;
align-items: center;
background: #fff4e6;
}
.toolbar {
display: flex;
gap: 8px;
padding: 12px;
border-block-start: 1px solid #ddd;
}
.toolbar .logout { margin-inline-start: auto; }
</style>
</head>
<body>
<section class="hero"><h1>Centred in both directions</h1></section>
<div class="toolbar">
<button>Save</button>
<button>Share</button>
<button class="logout">Log out</button>
</div>
</body>
</html>Watch out: The order property and flex-direction: row-reverse change only the visual order. Keyboard users and screen readers still follow the HTML order, so a reversed layout can make tabbing jump around confusingly. Change the HTML if the logical order needs to change.
Debugging flex layouts
When a flex layout behaves strangely, check these points in order:
- Is
display: flexon the parent, not on the items? Flex properties such asjustify-contentdo nothing on an element that is not a flex container. - Which way is the main axis? If you switched to
flex-direction: column,justify-contentandalign-itemsswap jobs. - Is an item refusing to shrink? Long words, URLs and images have a minimum content size. Adding
min-width: 0to the item lets it shrink below that size. - Open developer tools. Chrome, Edge and Firefox show a “flex” badge next to flex containers that draws the items and gaps on the page.
When to use CSS Flexbox
Use Flexbox when content should flow in one direction and items decide their own size: navigation bars, toolbars, button groups, media objects (image beside text) and rows of tags. When you need to line things up in rows and columns at the same time, CSS Grid is usually the better tool. The two work well together, and the blog post Flexbox vs Grid compares them in depth.
