⁑ Align Content
The align-content property controls space between multiple lines of flex items along the cross axis (when wrapping is enabled).
🔸 It only has an effect when flex-wrap: wrap (or wrap-reverse) is used and there is more than one row/column of items.
<style>
.flex-container {
display: flex;
flex-wrap: wrap; /* Allow wrapping */
height: 400px;
gap: 10px;
background-color: lightgrey;
padding: 10px;
}
.flex-item {
background: steelblue;
color: white;
margin: 5px;
padding: 50;
text-align: center;
}
</style>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
<div class="flex-item">9</div>
<div class="flex-item">10</div>
</div>🧱 Syntax
align-content: flex-start | flex-end | center | space-between | space-around🧭 Works Only With Multi-line Layouts
Requirement | Needed? |
|---|---|
Multiple lines of items | ✅ Yes |
| ✅ Yes |
Single-line flex | ❌ No effect |
🔄 Cross Axis Refresher
For
flex-direction: row→ cross axis is verticalFor
flex-direction: column→ cross axis is horizontal
🔍 Difference Between align-items and align-content
Property | Affects | Use Case |
|---|---|---|
| Positioning of individual items within each line | For aligning items inside each row |
| Spacing between rows or columns | For controlling vertical/horizontal space between lines |
🔔 If there's only one row, align-content has no effect.
🔹 Property Values Explained
🔸 flex-start
Lines are packed to the start of the cross axis.
.flex-container {
display: flex;
align-content: flex-start;
}🔸 flex-end
Lines are packed to the end of the cross axis.
.flex-container {
display: flex;
align-content: flex-end;
}🔸 center
Lines are packed toward the center of the container.
.flex-container {
display: flex;
align-content: center;
}🔸 space-between
Lines are evenly distributed, first at the top, last at the bottom.
.flex-container {
display: flex;
align-content: space-between;
}🔸 space-around
Equal space above and below each row.
.flex-container {
display: flex;
align-content: space-around;
}🧱 Align-Content Playground
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Align Content Playground</title>
<style>
.infographic-aligncontent {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-aligncontent[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.ha-inner { padding: 0.5rem; }
.ha-layout { display: flex; flex-direction: column; gap: 1.1rem; }
.ha-code {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
padding: 0.8rem 1.8rem 0.8rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.85rem;
color: #e5e5e5;
overflow-x: auto;
}
.ha-code .ha-prop { color: #c586c0; }
.ha-code .ha-val-hl { color: #ffd166; font-weight: 700; }
.ha-code .ha-sel { color: #f472b6; font-weight: 700; }
.ha-pills {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: center;
}
.ha-pill {
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 0.74rem;
font-weight: 700;
padding: 0.42rem 0.75rem;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.ha-pill:hover { border-color: var(--accent); }
.ha-pill.ha-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.ha-stage-outer {
background: var(--paper-alt);
border-radius: 10px;
padding: 1rem;
}
.ha-stage-label {
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 0.65rem;
color: var(--ink-soft);
margin-bottom: 0.5rem;
text-align: center;
}
.ha-toggle {
display: flex;
background: var(--paper-alt);
border: 1px solid var(--line);
border-radius: 999px;
padding: 0.25rem;
gap: 0.25rem;
}
.ha-toggle button {
flex: 1;
border: none;
background: transparent;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 0.72rem;
font-weight: 700;
padding: 0.5rem 0.4rem;
border-radius: 999px;
cursor: pointer;
transition: background 0.2s ease, color 0.2s ease;
}
.ha-toggle button.ha-on { background: var(--accent); color: #fff; }
.ha-stage {
background: lightgrey;
border-radius: 8px;
padding: 12px;
width: 300px;
height: 260px;
max-width: 100%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
gap: 8px;
align-content: flex-start;
transition: width 0.3s ease, height 0.3s ease;
}
.ha-stage.ha-col-mode { width: 460px; height: 200px; }
.ha-flex-item {
background: steelblue;
color: white;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-weight: 700;
text-align: center;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 45px;
flex-shrink: 0;
box-sizing: border-box;
}
.ha-note {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 0.78rem;
color: var(--ink-soft);
}
</style>
</head>
<body>
<div class="infographic-aligncontent" id="ha-root">
<div class="ha-inner">
<div class="ha-layout">
<div class="ha-code" id="code-out"></div>
<div class="ha-toggle">
<button class="ha-on" id="btn-row">row</button>
<button id="btn-column">column</button>
</div>
<div class="ha-pills" id="content-pills">
<button class="ha-pill ha-on" data-val="flex-start">flex-start</button>
<button class="ha-pill" data-val="flex-end">flex-end</button>
<button class="ha-pill" data-val="center">center</button>
<button class="ha-pill" data-val="space-between">space-between</button>
<button class="ha-pill" data-val="space-around">space-around</button>
</div>
<div class="ha-stage-outer">
<div class="ha-stage-label" id="stage-label">tall 260px container, wrapped into 3 short lines — lots of leftover vertical space to distribute</div>
<div class="ha-stage" id="stage">
<div class="ha-flex-item">1</div>
<div class="ha-flex-item">2</div>
<div class="ha-flex-item">3</div>
<div class="ha-flex-item">4</div>
<div class="ha-flex-item">5</div>
<div class="ha-flex-item">6</div>
</div>
</div>
<div class="ha-note" id="note-out"></div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('ha-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const stage = document.getElementById('stage');
const codeOut = document.getElementById('code-out');
const note = document.getElementById('note-out');
const label = document.getElementById('stage-label');
const items = Array.from(stage.querySelectorAll('.ha-flex-item'));
const btnRow = document.getElementById('btn-row');
const btnColumn = document.getElementById('btn-column');
let direction = 'row';
let align = 'flex-start';
const labels = {
'row': 'tall 260px container, wrapped into 3 short lines — lots of leftover vertical space to distribute',
'column': 'wide 460px container, wrapped into 3 short columns — lots of leftover horizontal space to distribute'
};
const notesRow = {
'flex-start': 'This only matters because the container wraps into multiple LINES — align-content controls the lines as a group. Here all three lines pack toward the top.',
'flex-end': 'All three lines pack toward the bottom, leaving the leftover vertical space above them.',
'center': 'All three lines bunch together in the vertical middle, with equal empty space above and below the whole group.',
'space-between': 'The first and last lines touch the top and bottom edges, with the leftover space split evenly between the lines in between.',
'space-around': 'Each line gets equal space above and below it — so the gap between lines ends up twice as tall as the gaps at the very top and bottom.'
};
const notesColumn = {
'flex-start': 'With flex-direction: column, wrapped lines are now vertical COLUMNS side by side — align-content packs the columns toward the LEFT.',
'flex-end': 'The columns pack toward the RIGHT, leaving the leftover horizontal space on the left.',
'center': 'The columns bunch together in the horizontal middle, with equal empty space on both sides.',
'space-between': 'The first and last columns touch the left and right edges, with leftover space split evenly between the columns in between.',
'space-around': 'Each column gets equal space on both sides — so the gap between columns ends up twice as wide as the gaps at the very edges.'
};
function currentNotes() {
return direction === 'row' ? notesRow : notesColumn;
}
function animateChange() {
const firstRects = items.map(el => el.getBoundingClientRect());
stage.classList.toggle('ha-col-mode', direction !== 'row');
stage.style.flexDirection = direction;
stage.style.alignContent = align;
void stage.offsetHeight;
const lastRects = items.map(el => el.getBoundingClientRect());
items.forEach((el, i) => {
const dx = firstRects[i].left - lastRects[i].left;
const dy = firstRects[i].top - lastRects[i].top;
el.style.transition = 'none';
el.style.transform = 'translate(' + dx + 'px, ' + dy + 'px)';
});
requestAnimationFrame(() => {
items.forEach(el => {
el.style.transition = 'transform 0.4s cubic-bezier(0.22, 1, 0.36, 1)';
el.style.transform = 'translate(0, 0)';
});
});
label.textContent = labels[direction];
codeOut.innerHTML = '<span class="ha-sel">.flex-container</span> {\n ' +
'<span class="ha-prop">display</span>: flex;\n ' +
'<span class="ha-prop">flex-direction</span>: <span class="ha-val-hl">' + direction + '</span>;\n ' +
'<span class="ha-prop">flex-wrap</span>: wrap;\n ' +
'<span class="ha-prop">align-content</span>: <span class="ha-val-hl">' + align + '</span>;\n}';
note.textContent = currentNotes()[align];
}
function setDirection(newDir, btn) {
if (direction === newDir) return;
direction = newDir;
[btnRow, btnColumn].forEach(b => b.classList.remove('ha-on'));
btn.classList.add('ha-on');
animateChange();
}
btnRow.addEventListener('click', () => setDirection('row', btnRow));
btnColumn.addEventListener('click', () => setDirection('column', btnColumn));
document.getElementById('content-pills').querySelectorAll('.ha-pill').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.ha-pill').forEach(p => p.classList.remove('ha-on'));
btn.classList.add('ha-on');
align = btn.getAttribute('data-val');
animateChange();
});
});
animateChange();
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});✅ Summary
Use
align-contentonly when items wrap onto multiple lines.Combine it with
flex-wrapandheight/widthfor best results.