If you've been building websites for a while, you likely remember the dark ages of layout. We used float: left, we cleared floats with pseudo-elements, and we prayed to the alignment gods. Then came CSS Flexbox, officially known as the Flexible Box Layout Module, and it changed everything.
Flexbox is a one-dimensional layout method for laying out items in rows or columns. Items flex to fill additional space and shrink to fit into smaller spaces. Unlike traditional block layouts which stack vertically by default, or inline layouts which sit side-by-side but can't be easily controlled vertically, Flexbox gives you powerful distribution capabilities along a single axis.
In this CSS Flexbox Guide, we will explore the terminology, the properties, and the logic that makes Flexbox the go-to solution for component-level layouts. Whether you are building a navigation bar, a card gallery, or a complex form, understanding Flexbox is non-negotiable for modern frontend development.
Understanding the Axes: Main vs. Cross
To truly master Flexbox, you must stop thinking in terms of "left and right" or "top and bottom" and start thinking in terms of axes. Flexbox operates on two axes:
- Main Axis: The primary axis along which flex items are laid out. It runs in the direction defined by the
flex-directionproperty (e.g., horizontal for rows, vertical for columns). - Cross Axis: The axis perpendicular to the main axis. Its direction depends on the main axis direction.
Most Flexbox properties are designed to control alignment on one of these two axes. For example, justify-content always aligns items along the main axis, while align-items always aligns items along the cross axis. If you get confused about which property to use, simply ask yourself: "Which axis do I want to control?"
The Holy Trinity of Flexbox Properties
While there are over a dozen properties related to Flexbox, three of them handle 90% of your daily layout needs.
1. flex-direction
This property establishes the main axis. It defines whether items flow in a row, a column, and in which direction they start.
row(default): Items flow left to right.row-reverse: Items flow right to left.column: Items flow top to bottom.column-reverse: Items flow bottom to top.
Changing flex-direction physically rotates your mental model of the layout. If you switch to column, your "left" and "right" become "top" and "bottom" relative to the main axis. This is why justify-content starts aligning things vertically when flex-direction is set to column.
2. justify-content
This is perhaps the most used Flexbox property. It defines how the browser distributes space between and around content items along the main axis.
flex-start: Items are packed toward the start line.flex-end: Items are packed toward the end line.center: Items are centered along the line.space-between: Items are evenly distributed; first item is on the start line, last item on the end line.space-around: Items have equal space around them.space-evenly: Items are distributed so that the spacing between any two items (and the space to the edges) is equal.
Pro tip: Use justify-content: space-between for navigation bars where you want the logo on the far left and the CTA button on the far right. Use space-around or space-evenly for tag clouds or pill menus.
3. align-items
While justify-content handles the main axis, align-items handles the cross axis. This property aligns flex items within the current line of the flex container.
stretch(default): Items stretch to fill the container.flex-start: Items are placed at the start of the cross axis.flex-end: Items are placed at the end of the cross axis.center: Items are centered on the cross axis.baseline: Items are aligned such as their baselines align.
The stretch value is the default for a reason. It's incredibly useful for creating equal-height columns. If you have three cards with different amounts of text, setting them to display flex with default alignment will make them all the height of the tallest card.
Flexbox for Multi-Line Layouts
So far, we've assumed all items fit on one line. But what happens when you have 20 items in a row?
flex-wrap
By default, Flexbox tries to squeeze all items into one line, shrinking them if necessary. The flex-wrap property controls this.
nowrap(default): All flex items will be on one line.wrap: Flex items will wrap onto multiple lines.wrap-reverse: Flex items will wrap onto multiple lines from bottom to top.
align-content
This property aligns a flex container's lines within the flex container when there is extra space in the cross-axis. It is similar to justify-content but for the cross axis and for lines of items, not individual items.
Warning: align-content has no effect when the flex container has only a single line of items (i.e., flex-wrap: nowrap). This is a common mistake beginners make. If you change align-content and nothing happens, check your flex-wrap setting.
The Modern Way to Add Space: gap
For years, Flexbox users hacked margins to create space between items. This was messy because margins didn't collapse perfectly. Enter the gap property.
The gap property (and row-gap / column-gap) was originally part of CSS Grid but is now fully supported in Flexbox. It specifies the size of the gutter (space) between flex rows and flex columns.
Using gap: 1rem is cleaner than margin-right: 1rem on every item because you don't have to use the :last-child pseudo-class to remove the margin from the last item.
Real-World Flexbox Use Cases
1. The Holy Grail Layout
Historically, the "Holy Grail" layout (Header, Footer, 3 Columns) was difficult. With Flexbox, it's trivial. The container is display: flex; flex-direction: column; min-height: 100vh;. The main content area gets flex: 1 to push the footer down.
2. Centering Anything
The vertical centering problem used to be the bane of a developer's existence. With Flexbox, centering an element both horizontally and vertically takes three lines:
.parent {
display: flex;
justify-content: center;
align-items: center;
}
3. Card Grids
While CSS Grid is often better for two-dimensional grids, a simple row of cards is perfect for Flexbox. Set display: flex; flex-wrap: wrap; on the container. Give each card a width and use gap for spacing. The cards will wrap naturally as the screen resizes.
Flexbox vs. CSS Grid
One of the most common questions is: "Should I use Flexbox or Grid?" The answer is usually: Why not both?
Use Flexbox when: You are laying out items in a one-dimensional context (a row OR a column), or aligning items vertically within a row (like buttons in a navbar).
Use CSS Grid when: You need precise control over two dimensions (rows and columns simultaneously), or you are designing a complex page layout macro-structure.
Common Mistakes to Avoid
- Forgetting to Reset Default Browser Styles (margins on headings/paragraphs can break flex layouts).
- Confusing Align-Items with Align-Content (Content is for lines, Items is for individual elements).
- Using Flexbox for Everything (Over-nesting 5 levels of flex containers is a sign you should switch to Grid).
Pro Tips for Flexbox Mastery
- Use the
flexshorthand property. Instead of writingflex-grow: 1; flex-shrink: 1; flex-basis: 0%;, just writeflex: 1;. - Use
margin: autoon a flex item to absorb extra space. This is a great trick for pushing a specific item (like a "Log Out" button) to the far right of a navbar. - Combine Flexbox with
position: absolutefor overlays. - Don't forget accessibility. Avoid using
orderunless strictly necessary, as it can confuse screen reader users.
Now that you understand the theory, you should try using the interactive Flexbox Generator to visualize these changes in real-time.