🧭 Flex Direction
The flex-direction property controls the direction in which flex items are laid out within a container. This is the first major step in shaping your layout using Flexbox.
Master code block to be used for further examples
<style>
/*All the changes are made here further*/
.flex-container {
display: flex;
background-color: lightgrey;
padding: 10px;
}
.flex-item {
background: steelblue;
color: white;
margin: 5px;
padding: 20px;
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>🧱 Syntax
flex-direction: row | row-reverse | column | column-reverse;🔀 Values Explained
▶️ row (Default)
Items are placed left to right (in horizontal row).
Main axis: horizontal
Cross axis: vertical
.flex-container {
display: flex;
flex-direction: row;
}◀️ row-reverse
Items are placed right to left.
Order is reversed, but DOM structure remains the same.
Main axis: horizontal (reversed)
.flex-container {
display: flex;
flex-direction: row-reverse;
}🔽 column
Items stack top to bottom (in vertical column).
Main axis: vertical
Cross axis: horizontal
.flex-container {
display: flex;
flex-direction: column;
}🔼 column-reverse
Items stack bottom to top, reversing the visual flow.
Main axis: vertical (reversed)
.flex-container {
display: flex;
flex-direction: column-reverse;
}🔀 Flex Direction Playground
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Flex Direction Playground</title>
<style>
.infographic-flexdirection {
--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-flexdirection[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-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.78rem;
font-weight: 700;
padding: 0.45rem 0.9rem;
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-wrap {
background: var(--paper-alt);
border-radius: 10px;
padding: 0.8rem;
position: relative;
}
.ha-arrow-row {
display: flex;
align-items: center;
justify-content: center;
gap: 0.4rem;
margin-bottom: 0.6rem;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 0.7rem;
color: var(--ink-soft);
}
.ha-arrow-icon {
font-size: 1rem;
transition: transform 0.4s ease;
display: inline-block;
}
.ha-stage {
background: lightgrey;
border-radius: 8px;
padding: 14px;
min-height: 230px;
display: flex;
box-sizing: border-box;
position: relative;
}
.ha-flex-item {
background: steelblue;
color: white;
margin: 5px;
padding: 20px;
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;
min-width: 40px;
min-height: 40px;
box-sizing: border-box;
position: relative;
}
.ha-flex-item.ha-first {
box-shadow: 0 0 0 3px #ffd166;
}
.ha-flex-item .ha-order-badge {
position: absolute;
top: -8px;
left: -8px;
background: #ffd166;
color: #333;
font-size: 0.62rem;
font-weight: 800;
width: 18px;
height: 18px;
border-radius: 50%;
display: none;
align-items: center;
justify-content: center;
}
.ha-flex-item.ha-first .ha-order-badge { display: flex; }
.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-note {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 0.78rem;
color: var(--ink-soft);
}
</style>
</head>
<body>
<div class="infographic-flexdirection" id="ha-root">
<div class="ha-inner">
<div class="ha-layout">
<div class="ha-code" id="code-out"></div>
<div class="ha-pills" id="direction-pills">
<button class="ha-pill ha-on" data-val="row">row</button>
<button class="ha-pill" data-val="row-reverse">row-reverse</button>
<button class="ha-pill" data-val="column">column</button>
<button class="ha-pill" data-val="column-reverse">column-reverse</button>
</div>
<div class="ha-stage-wrap">
<div class="ha-arrow-row">
<span>flow direction:</span>
<span class="ha-arrow-icon" id="arrow-icon">→</span>
</div>
<div class="ha-stage" id="stage">
<div class="ha-flex-item ha-first"><span class="ha-order-badge">start</span>1</div>
<div class="ha-flex-item">2</div>
<div class="ha-flex-item">3</div>
<div class="ha-flex-item">4</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 arrowIcon = document.getElementById('arrow-icon');
const items = Array.from(stage.querySelectorAll('.ha-flex-item'));
const notes = {
'row': 'Items flow left → right, in source order (1, 2, 3, 4). This is the default.',
'row-reverse': 'Items still flow horizontally, but reversed: source order 1,2,3,4 renders right-to-left as 4,3,2,1.',
'column': 'Items now stack top → bottom instead of side by side, still in source order.',
'column-reverse': 'Items stack vertically but reversed: item 4 ends up on top, item 1 on the bottom.'
};
const arrows = {
'row': '→',
'row-reverse': '←',
'column': '↓',
'column-reverse': '↑'
};
// FLIP animation: capture First rects, apply the layout change, capture Last rects,
// then Invert with a transform and Play back to zero so the reflow looks like real motion.
function animateDirectionChange(newDirection) {
const firstRects = items.map(el => el.getBoundingClientRect());
stage.style.flexDirection = newDirection;
// force reflow so getBoundingClientRect reflects the new layout
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)';
});
// next frame: play the animation back to rest
requestAnimationFrame(() => {
items.forEach(el => {
el.style.transition = 'transform 0.45s cubic-bezier(0.22, 1, 0.36, 1)';
el.style.transform = 'translate(0, 0)';
});
});
}
document.getElementById('direction-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');
const val = btn.getAttribute('data-val');
animateDirectionChange(val);
arrowIcon.textContent = arrows[val];
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">' + val + '</span>;\n}';
note.textContent = notes[val];
});
});
// initialize
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">row</span>;\n}';
note.textContent = notes['row'];
})();
</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!');
});🧭 Main Axis vs Cross Axis
Property | Main Axis Direction | Cross Axis Direction |
|---|---|---|
| ➡ Left → Right | ⬇ Top → Bottom |
| ⬅ Right → Left | ⬇ Top → Bottom |
| ⬇ Top → Bottom | ➡ Left → Right |
| ⬆ Bottom → Top | ➡ Left → Right |
🔑 Main Axis = Flow of items
🔑 Cross Axis = Perpendicular to main axis
✅ These axes matter for properties like justify-content (main axis) and align-items (cross axis)
🛠️ Practical Layout Switches
Use Case | Flex-direction Value |
|---|---|
Horizontal nav bar |
|
Reverse nav bar for RTL language |
|
Vertical sidebar menu |
|
Chat app (latest message at bottom) |
|
✅ Summary
flex-directioncontrols the flow direction of items in a Flexbox container.You can switch from row to column layout easily with one line of CSS.
Understanding main and cross axis is crucial for aligning and distributing space later.