Still using floats and hacks to build layouts?
You don’t have to.
Flexbox makes arranging items predictable and fast: switch a parent to display: flex and its direct children line up, center, wrap, or stretch with a few rules.
In this tutorial you’ll learn the core split between container and item controls, how axes work, and the small properties that fix most layout headaches.
Expect hands-on examples and quick wins you can drop into a nav, card grid, or centered hero.
Ready to stop guessing and start building responsive layouts?
Core Flexbox Tutorial Overview and Immediate How-To

Flexbox is a one-dimensional CSS layout system that distributes items along a single line and aligns them across that line. It solves the old problem of forcing divs to sit side by side or centering things without guessing padding values. Before Flexbox, developers used floats, inline-block hacks, or table-display tricks that broke easily on different screen sizes. Flexbox gives you a clean way to build navigation bars, button groups, card layouts, and responsive sections that adjust to available space.
To activate Flexbox, you add display: flex; to a parent element. That parent becomes a flex container, and all its direct children become flex items. The container controls how items are spaced, aligned, and sized along the main axis (usually left to right) and the cross axis (usually top to bottom). Items inside the container follow Flexbox rules instead of the normal block and inline behavior you’re used to in regular HTML flow.
The container and items each get their own set of properties. Container properties (like justify-content and align-items) control the group as a whole. Item properties (like flex-grow and align-self) let you adjust individual children. Once you understand this split, building layouts becomes more predictable. Here’s a simple example:
.container {
display: flex;
justify-content: space-between;
}
.item {
flex: 1;
}
<div class="container">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
</div>
In this code, the three items sit in a horizontal row with equal space between them, and each item gets an equal share of available width. That’s Flexbox in action.
Why Flexbox Behaves the Way It Does: Axes, Sizing & Distribution

Flexbox layout decisions all hinge on the primary axis, which you control with flex-direction. By default, flex-direction: row; makes the main axis run left to right, so items line up horizontally. Switch to flex-direction: column; and the main axis runs top to bottom, stacking items vertically. The cross axis is always perpendicular to the main axis. If your main axis is horizontal, the cross axis is vertical, and vice versa.
Items default to bunching up at the start of the main axis and stretching to fill the cross axis. That means a row of boxes will hug the left edge and stretch to match the tallest box’s height. Flexbox treats width and height suggestions as hypothetical sizes instead of hard rules. An item with width: 2000px in a 500px-wide flex row won’t break the layout. Flexbox will shrink it to fit unless you explicitly prevent shrinking.
Here’s what drives Flexbox behavior under the hood:
Main axis direction. Set by flex-direction (row, row-reverse, column, column-reverse). Everything else follows this choice.
Cross axis default. Items stretch to fill the container’s cross axis size unless you override with align-items.
Hypothetical size. Properties like width, flex-basis, and content size become starting suggestions, not fixed dimensions.
Space distribution. Extra space on the main axis gets divided by justify-content. Extra space on the cross axis (in multi-line layouts) gets divided by align-content.
Growing and shrinking. Items can grow (flex-grow) to consume leftover space or shrink (flex-shrink) to fit when the container is too small, based on proportional ratios you set.
Essential Flexbox Properties for Containers

When you set display: flex; on a container, you unlock a set of properties that control how the group of items behaves. These properties live on the parent element and affect all direct children at once.
flex-direction
flex-direction sets the main axis. Use row (default) for horizontal layouts, column for vertical stacks. Add -reverse to flip the order visually. row-reverse makes items flow right to left, and column-reverse stacks them bottom to top. Changing direction swaps which axis is “main” and which is “cross,” so justify-content and align-items follow the new orientation.
justify-content
justify-content distributes items along the main axis. Common values include flex-start (bunch at the start), center (group in the middle), flex-end (push to the end), space-between (first item at start, last at end, equal gaps in between), space-around (equal space on both sides of each item), and space-evenly (perfectly equal gaps everywhere). This property only affects the group. There’s no “justify-self” in Flexbox.
align-items
align-items aligns each item on the cross axis within its row or column. Use stretch (default) to make items fill the cross axis size, flex-start to align to the top or left edge, flex-end to align to the bottom or right, center to center each item, or baseline to line up text baselines. Unlike justify-content, align-items controls individual item positions, but it applies the same rule to every item unless you override with align-self.
flex-wrap
flex-wrap controls whether items stay on one line or wrap to new lines when they run out of space. The default is nowrap, forcing everything onto a single line and potentially shrinking items. Use wrap to let items spill onto multiple rows or columns, or wrap-reverse to stack new lines in reverse order. When wrapping is active, align-content kicks in to distribute those lines along the cross axis.
| Property | Purpose | Common Values |
|---|---|---|
| flex-direction | Sets main axis direction | row, column, row-reverse, column-reverse |
| justify-content | Distributes group on main axis | flex-start, center, space-between, space-evenly |
| align-items | Aligns items on cross axis | stretch, flex-start, center, baseline |
| flex-wrap | Controls single vs. multi-line layout | nowrap, wrap, wrap-reverse |
Flexbox Item-Level Controls for Precise Layout

While container properties control the group, item level properties let you fine tune individual children. These properties live on the flex items themselves and override or extend the container’s rules.
flex-grow
flex-grow decides how much of the leftover space an item gets. The default is 0, meaning items don’t grow beyond their content or flex-basis size. Set flex-grow: 1; and the item will expand to fill available space. If multiple items have flex-grow values, space is split proportionally. An item with flex-grow: 2; gets twice the share of an item with flex-grow: 1;.
flex-shrink
flex-shrink is the opposite of flex-grow. It controls how much an item shrinks when the container is too small. The default is 1, so all items shrink equally. If you set one item to flex-shrink: 3; and another to flex-shrink: 1;, the first item will shrink three times as much. Set flex-shrink: 0; to prevent an item from shrinking at all. Useful for icons or logos that need to stay a fixed size.
flex-basis
flex-basis sets the hypothetical size of an item before growing or shrinking happens. In a row, it behaves like width. In a column, like height. You can use pixel values (flex-basis: 200px;), percentages (flex-basis: 50%;), or auto (uses the item’s content size). Setting flex-basis: 0; treats the item as having zero starting size, which changes how flex-grow distributes space. The item grows from nothing instead of from its content width.
order and align-self
order changes the visual order of items without touching the HTML. The default is 0, and items with the same order value stay in source order. Higher numbers move items to the end. Negative numbers move them to the start. Remember: this only affects visual layout. Screen readers and keyboard navigation still follow the DOM order, so don’t rely on order for accessibility.
align-self overrides the container’s align-items setting for a single item. Use it to center one item while others stretch, or to push one item to the bottom of a row while others align to the top.
Here are common pitfalls when working with item level properties:
Visual vs. source order. order changes what you see, not the DOM. Assistive tech still reads items in HTML order.
Negative values. flex-grow and flex-shrink don’t accept negative numbers. If you try, the browser ignores the rule.
flex-basis vs. width. flex-basis takes priority in Flexbox calculations, but mixing both can cause confusion. Stick to flex-basis when using Flexbox.
Shorthand resets. The flex shorthand resets all three values. Writing flex: 1; sets flex-grow: 1; flex-shrink: 1; flex-basis: 0%;, which might not be what you expect.
Here’s an example using the flex shorthand:
.item {
flex: 2 1 100px;
/* flex-grow: 2, flex-shrink: 1, flex-basis: 100px */
}
This item starts at 100px, can grow to take twice the share of other items, and can shrink proportionally if space runs out.
Centering Content with Flexbox

Flexbox makes centering simple. For years, developers used margin hacks, absolute positioning, or transform tricks to center things. Flexbox does it in two lines of CSS.
To center items horizontally and vertically inside a container, set justify-content: center; and align-items: center; on the parent. The first centers along the main axis, the second centers along the cross axis. If your main axis is horizontal (the default), items center left to right and top to bottom. If you’ve set flex-direction: column;, they center top to bottom and left to right.
For single item centering, you can skip container properties and use margin: auto; on the item itself. In a flex container, auto margins consume all available space, pushing the item to the perfect center in both directions. Here are the four centering techniques:
Horizontal centering. justify-content: center; on a row container, or margin-left: auto; margin-right: auto; on the item.
Vertical centering. align-items: center; on the container, or margin-top: auto; margin-bottom: auto; on the item.
Both axes at once. Combine justify-content: center; and align-items: center; on the container for perfect centering.
Single item with auto margin. Set margin: auto; on the item to center it in both directions without touching the container.
Responsive Flexbox Layout Patterns

Flexbox shines when you need layouts that adapt to screen size without writing a dozen media queries. Items automatically reflow, resize, and wrap based on available space, making it perfect for navigation bars, card grids, and mobile first designs.
Responsive navigation bars are one of the most common Flexbox patterns. On wide screens, nav links sit in a horizontal row with flex-direction: row; and justify-content: space-between;. On narrow screens, a media query switches to flex-direction: column; and centers each link with align-items: center;. The layout transforms from horizontal to vertical without changing the HTML.
Equal height columns used to require JavaScript or table hacks. Flexbox does it automatically. When you set display: flex; on a container, all direct children stretch to match the tallest item’s height by default (thanks to align-items: stretch;). This works for card layouts where each card has different amounts of text but you want all cards to line up visually. Add flex-wrap: wrap; and the cards will flow onto new rows when the container gets too narrow, while still keeping equal heights within each row.
Mobile first wrapping patterns start with a single column on small screens and expand to multi-column grids on larger screens. Set flex-direction: column; as the default, then use a media query at your breakpoint to switch to flex-direction: row; and flex-wrap: wrap;. Each item gets flex: 1 1 200px; so it grows to fill space but wraps to a new row if it would shrink below 200px. This creates a fluid grid that adapts to any screen width without hardcoded column counts.
Common responsive layouts built with Flexbox:
Responsive navbar. Horizontal on desktop, stacked on mobile using flex-direction media queries.
Card grids. Equal height cards that wrap to new rows when space runs out.
Sticky footer. A footer that stays at the bottom of the viewport by setting flex: 1; on the main content area.
Image gallery. Flexible image sizing with flex-wrap: wrap; and proportional flex-grow values.
Two-column split. Sidebar and main content using flex: 0 0 250px; for the sidebar and flex: 1; for the content.
Debugging Flexbox Layouts & Common Pitfalls

Even with Flexbox’s predictable rules, you’ll run into layout bugs. Most issues come from mixing old layout assumptions with new flex behavior, or from browser quirks that trip up specific properties.
One common mistake is expecting align-content to work on single line containers. align-content only affects multi-line layouts created by flex-wrap: wrap;. If your items don’t wrap, align-content does nothing. Another frequent issue is the conflict between flex-basis and width. Some browsers treat flex-basis: auto; as “use the width value,” while others calculate it from content size. Using the flex shorthand instead of setting properties individually avoids most of these inconsistencies.
Minimum size problems show up when text inputs or long unbreakable strings set a floor that prevents items from shrinking. Browsers give text inputs a default minimum width of around 170 to 200px, and long URLs or code snippets won’t break to a new line. The fix is setting min-width: 0; on flex items to override the browser’s default minimum. Be careful though. This can cause text overflow if you don’t add overflow: hidden; or similar handling. Visual order bugs happen when developers use order to rearrange items and forget that screen readers and keyboard focus still follow the DOM order. This creates accessibility issues where the visual layout doesn’t match the reading order.
| Issue | Cause | Solution | Notes |
|---|---|---|---|
| align-content not working | Single-line container (nowrap) | Add flex-wrap: wrap; | align-content only affects wrapped layouts |
| Items won’t shrink | Default min-width or long content | Set min-width: 0; on items | May cause text overflow; add overflow rules |
| flex-basis vs width conflict | Browser differences in auto handling | Use flex shorthand instead | Shorthand is more consistent across browsers |
| Visual order breaks accessibility | order property changes display, not DOM | Reorder HTML or use Grid instead | Screen readers follow source order |
Preventing Future Flexbox Issues

Writing clean Flexbox code from the start saves hours of debugging later. A few best practices will keep your layouts predictable and maintainable as your project grows.
Use the gap property for spacing between items instead of adding margins to every child. gap creates consistent gutters without edge cases where the first or last item gets extra margin. It’s supported in all modern browsers since early 2021, and it works with Grid and multi-column layouts too. If you need to support older browsers, use margin based fallbacks with :not(:last-child) selectors or wrapper elements.
Stick to the flex shorthand when setting grow, shrink, and basis values together. Writing flex: 1; is clearer and more reliable than setting three separate properties, because the shorthand applies smart defaults (flex: 1; becomes flex-grow: 1; flex-shrink: 1; flex-basis: 0%;). Avoid setting both width and flex-basis on the same item. Pick one and stick with it. Mixing the two creates confusion because browsers handle the conflict differently.
Test your layouts in multiple browsers, especially if you’re supporting older versions. Use Autoprefixer to automatically add vendor prefixes for legacy browsers like IE10 and IE11. These browsers use older Flexbox syntaxes that differ slightly from the modern spec, and Autoprefixer handles the translation for you.
Best practices to follow:
Use gap for spacing. Cleaner than per item margins and works across layout modes.
Prefer flex shorthand. flex: 1; is more predictable than separate grow, shrink, and basis rules.
Avoid unnecessary width on flex items. Let flex-basis handle sizing in Flexbox contexts.
Set min-width: 0 for overflow prone elements. Prevents text inputs and long strings from breaking layouts.
When to Seek More Help & Next Steps for Flexbox Mastery

If you’ve followed this tutorial and built a few practice layouts, you’ve covered the essentials. But Flexbox has edge cases, advanced patterns, and interaction with other CSS features (like Grid, position, and transforms) that take time to internalize. Knowing when to look for help and where to go next will speed up your learning.
Interactive demos and playgrounds are the fastest way to experiment with Flexbox properties. Tools like CodePen, JSFiddle, and CSS-Tricks’ Flexbox playground let you toggle values and see results instantly. Many tutorials include embedded demos with sliders for flex-grow, flex-shrink, and flex-basis so you can watch items resize in real time. Downloadable cheat sheets summarize all the properties, values, and common patterns on a single page you can keep open while coding.
The next step is building real projects. Start with small components (a navbar, a card layout, a product grid) and gradually work up to full page layouts. When you hit a layout that Flexbox can’t solve cleanly (like a two-dimensional grid with uneven rows and columns), that’s your signal to learn CSS Grid. Grid and Flexbox complement each other. Use Grid for page structure and Flexbox for component internals.
Next step resources to explore:
Interactive playgrounds. Experiment with properties in real time to see how changes affect layout.
CodePen Flexbox examples. Study annotated demos showing common patterns and edge case solutions.
Flexbox cheat sheets. Quick reference PDFs or posters summarizing all properties and values.
Final Words
You turned a plain container into a flexible layout by using display:flex and learned main and cross axes, container vs items, and key properties like justify-content, align-items, flex-direction, and flex-wrap.
You practiced item controls — flex-grow, flex-shrink, flex-basis, shorthand, order and align-self — plus centering tricks, responsive patterns, and debugging tips to fix real problems.
Practice a couple small examples and keep a cheat sheet handy — you’ll get comfortable fast. This flexbox tutorial gave the core moves; now build something and tweak until it feels right. You’ve got this.
FAQ
Q: Is Flexbox still relevant? Is Flexbox deprecated?
A: Flexbox is still relevant and not deprecated because modern browsers fully support it; it excels at one-dimensional layouts like navbars and cards, while Grid handles two-dimensional layouts.
Q: Is Flexbox difficult?
A: Flexbox isn’t difficult; the basics are simple: set display:flex, pick a direction, then use justify-content and align-items. Small practice projects make it intuitive quickly.
Q: How do I use Flexbox?
A: You use Flexbox by setting display:flex on a parent, choosing flex-direction, then using justify-content and align-items to position children, and tweaking flex-grow, flex-basis, or align-self for item sizing.

