CSS Flexible Box Layout, commonly known as Flexbox, is a CSS layout model designed for arranging items in a one-dimensional space -- either as a row or a column. Introduced as part of the CSS3 specification, Flexbox solves many of the layout challenges that plagued web developers for years: centering elements, creating equal-height columns, distributing space evenly, and building responsive layouts that adapt gracefully to different screen sizes.
Before Flexbox, developers relied on floats, inline-block, table display, and absolute positioning to achieve layouts. These techniques were workarounds rather than true layout solutions, leading to fragile code, clearfix hacks, and unpredictable behavior. Flexbox was purpose-built for layout and provides intuitive, predictable controls for distributing space and aligning content.
The Flexbox model revolves around two key concepts:
Understanding these two axes is fundamental to mastering Flexbox, because every alignment and distribution property works relative to one of these axes.
A flex container is any element with display: flex (or display: inline-flex for an inline-level container). Setting this property on a parent element makes all of its direct children become flex items automatically.
.container {
display: flex;
}
Once an element becomes a flex container, its children gain access to all flex item properties. The container itself gains access to properties that control how items are arranged: flex-direction, flex-wrap, justify-content, align-items, align-content, and gap.
Important: only direct children of the flex container become flex items. Nested elements inside those children are not affected by the flex layout unless they are themselves inside another flex container.
The difference between display: flex and display: inline-flex is how the container itself behaves in the document flow. flex creates a block-level container (taking the full width), while inline-flex creates an inline-level container (only as wide as its content). The internal flex behavior is identical.
The flex-direction property defines the main axis of the flex container, determining the direction in which flex items are placed. This is one of the most important Flexbox properties because it establishes the foundation for how all other flex properties behave.
.container {
display: flex;
flex-direction: row; /* Default: left to right */
flex-direction: row-reverse; /* Right to left */
flex-direction: column; /* Top to bottom */
flex-direction: column-reverse; /* Bottom to top */
}
The four possible values are:
| Value | Main Axis | Item Flow |
|---|---|---|
row | Horizontal | Left to right (LTR) |
row-reverse | Horizontal | Right to left |
column | Vertical | Top to bottom |
column-reverse | Vertical | Bottom to top |
When you change flex-direction from row to column, the main and cross axes swap. This means that justify-content (which works on the main axis) will now control vertical distribution, and align-items (which works on the cross axis) will control horizontal alignment. Understanding this axis swap is crucial for building layouts that change direction responsively.
By default, flex items try to fit onto a single line, even if it means overflowing or shrinking below their preferred size. The flex-wrap property controls whether items are allowed to wrap onto multiple lines when the container is too narrow.
.container {
display: flex;
flex-wrap: nowrap; /* Default: single line */
flex-wrap: wrap; /* Items wrap to next line */
flex-wrap: wrap-reverse; /* Items wrap upward */
}
nowrap (the default) forces all items onto one line. Items will shrink according to their flex-shrink values to fit. wrap allows items to flow onto additional lines when the container is not wide enough. New lines are added below (for row direction) or to the right (for column direction). wrap-reverse works like wrap but adds new lines in the opposite direction.
The flex-flow shorthand combines flex-direction and flex-wrap into a single declaration:
.container {
flex-flow: row wrap; /* direction + wrap */
}
Flex wrapping is essential for responsive design. A common pattern is to set items with a fixed flex-basis (e.g., 300px) and flex-wrap: wrap, allowing items to naturally wrap to new rows as the viewport shrinks.
The justify-content property controls how flex items are distributed along the main axis. It determines what happens to the extra space when flex items do not fill the entire main axis, or how items are spaced when they overflow.
.container {
display: flex;
justify-content: flex-start; /* Items packed to start (default) */
justify-content: flex-end; /* Items packed to end */
justify-content: center; /* Items centered */
justify-content: space-between; /* Equal space between items */
justify-content: space-around; /* Equal space around items */
justify-content: space-evenly; /* Equal space between and around */
}
The six values create different spacing patterns:
The space-between value is particularly popular for navigation layouts where you want the logo on the left and nav links on the right. The space-evenly value is ideal when you want perfectly uniform gaps throughout.
While justify-content controls the main axis, align-items controls how flex items are aligned along the cross axis. For a row layout, this means vertical alignment; for a column layout, horizontal alignment.
.container {
display: flex;
align-items: stretch; /* Items stretch to fill cross axis (default) */
align-items: flex-start; /* Items aligned to cross-axis start */
align-items: flex-end; /* Items aligned to cross-axis end */
align-items: center; /* Items centered on cross axis */
align-items: baseline; /* Items aligned by text baseline */
}
The stretch default is why flex items in a row layout automatically fill the full height of the container. Setting align-items to flex-start, center, or flex-end causes items to take only their natural height and align accordingly.
The baseline value aligns items based on their text baseline. This is particularly useful when items have different font sizes or padding but you want their text content to align visually.
The align-content property only applies when flex items wrap onto multiple lines (flex-wrap: wrap). It controls how the lines themselves are distributed along the cross axis. If there is only one line of items, align-content has no effect.
.container {
display: flex;
flex-wrap: wrap;
align-content: flex-start; /* Lines packed to start */
align-content: flex-end; /* Lines packed to end */
align-content: center; /* Lines centered */
align-content: space-between; /* Equal space between lines */
align-content: space-around; /* Equal space around lines */
align-content: stretch; /* Lines stretch to fill (default) */
}
Think of align-content as the cross-axis equivalent of justify-content, but for wrapped lines instead of individual items. It controls the spacing between rows of items when wrapping occurs.
While container properties control the overall layout, flex item properties control how individual items behave within the container. The three core item properties are flex-grow, flex-shrink, and flex-basis.
The flex-grow property defines how much an item should grow relative to other items when there is extra space available. The default value is 0, meaning items do not grow by default.
.item { flex-grow: 0; } /* Default: don't grow */
.item { flex-grow: 1; } /* Grow to fill available space */
.item { flex-grow: 2; } /* Grow twice as much as flex-grow: 1 items */
If all items have flex-grow: 1, they share the extra space equally. If one item has flex-grow: 2 and the rest have flex-grow: 1, the grow-2 item gets twice the extra space. The values are proportional -- flex-grow: 2 and flex-grow: 4 behave the same as 1 and 2.
The flex-shrink property defines how much an item should shrink relative to other items when there is not enough space. The default value is 1, meaning all items shrink equally.
.item { flex-shrink: 1; } /* Default: shrink equally */
.item { flex-shrink: 0; } /* Don't shrink at all */
.item { flex-shrink: 2; } /* Shrink twice as much */
Setting flex-shrink: 0 prevents an item from shrinking below its natural size. This is useful for fixed-width elements like sidebars or icons that should not compress.
The flex-basis property sets the initial main size of an item before flex-grow and flex-shrink are applied. It can be a length value (px, rem, %), the keyword auto (use the item's width/height), or content (size based on content).
.item { flex-basis: auto; } /* Default: use width/height */
.item { flex-basis: 200px; } /* Start at 200px, then grow/shrink */
.item { flex-basis: 30%; } /* Start at 30% of container */
.item { flex-basis: 0; } /* Ignore content size, distribute all space */
flex-basis: 0 is often used with flex-grow to distribute all space proportionally, ignoring content size. flex-basis: auto respects the item's content or explicitly set width, then distributes only the remaining space.
The flex shorthand combines flex-grow, flex-shrink, and flex-basis into a single declaration. It is the recommended way to set flex item properties because it has sensible defaults that differ from the individual properties.
.item { flex: 0 1 auto; } /* Default: don't grow, shrink, auto basis */
.item { flex: 1; } /* Same as: flex: 1 1 0 */
.item { flex: auto; } /* Same as: flex: 1 1 auto */
.item { flex: none; } /* Same as: flex: 0 0 auto */
.item { flex: 2 0 200px; } /* Grow 2x, don't shrink, start at 200px */
Common patterns:
The order property controls the visual order of flex items without changing the HTML source order. Items are arranged in ascending order value. The default is 0, and negative values are allowed.
.item-a { order: 3; } /* Appears third */
.item-b { order: 1; } /* Appears first */
.item-c { order: 2; } /* Appears second */
The order property is useful for responsive design. For example, you might want a sidebar to appear below the main content on mobile but to the left on desktop. Using order with media queries achieves this without duplicating HTML.
Accessibility note: The order property changes visual order but not the DOM order. Screen readers and keyboard tab order still follow the source order. Use order for visual adjustments only, not for meaningful content reordering.
The align-self property allows an individual item to override the container's align-items value. It accepts the same values: auto, flex-start, flex-end, center, baseline, and stretch.
.container {
display: flex;
align-items: flex-start; /* All items at top */
}
.special-item {
align-self: flex-end; /* This item at bottom */
}
This is useful when most items should be aligned one way but a specific item needs different alignment, such as a "Learn More" button that should be anchored to the bottom of a card while other content is top-aligned.
The most common use case: centering an element both horizontally and vertically.
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
A logo on the left, nav links on the right.
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
Push the footer to the bottom of the page when content is short.
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* Grows to push footer down */
}
Cards in a row that all have the same height, regardless of content length.
.card-row {
display: flex;
gap: 1rem;
}
.card {
flex: 1;
display: flex;
flex-direction: column;
}
.card-content {
flex: 1; /* Fills remaining space */
}
Items that wrap to new rows as the container shrinks.
.grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.grid-item {
flex: 1 1 300px; /* Grow, shrink, min-width 300px */
}
Flexbox and CSS Grid are complementary layout systems, not competitors. Each excels in different scenarios:
| Aspect | Flexbox | CSS Grid |
|---|---|---|
| Dimensions | One-dimensional (row or column) | Two-dimensional (rows and columns) |
| Best for | Components, nav bars, centering | Page layouts, dashboards, galleries |
| Content vs Layout | Content-driven sizing | Layout-driven sizing |
| Wrapping | Items wrap freely | Explicit row/column structure |
| Use Together | Often combined: Grid for page layout, Flexbox for components within grid cells | |
A common approach in modern web development is to use CSS Grid for the overall page layout (header, sidebar, main, footer) and Flexbox for the components within those areas (navigation links, card content, form elements). This combination leverages the strengths of both systems.
flex: 1 over separate flex-grow, flex-shrink, and flex-basis declarations. The shorthand has better defaults and is more readable.Our CSS Flexbox Generator lets you experiment with all Flexbox properties visually. Set container properties like flex-direction, flex-wrap, justify-content, align-items, align-content, and gap using dropdown menus. Add or remove child items (up to 12) and click any item in the preview to edit its individual flex-grow, flex-shrink, flex-basis, order, and align-self properties. The live preview updates in real time, showing colored boxes that move and resize as you adjust settings. When you are satisfied with your layout, click Copy CSS to copy the production-ready CSS code to your clipboard.
The generator is perfect for learning Flexbox interactively, prototyping layouts quickly, or generating CSS for production use. Everything runs client-side in your browser -- no data is sent to any server. Try it now and master Flexbox in minutes.