Introduction to Flexbox
CSS Flexbox, formally known as the Flexible Box Layout module, represents a fundamental shift in how developers approach web layout design. Before flexbox, developers relied heavily on float, positioning, and display table properties to achieve complex layouts--approaches that often required workarounds and resulted in brittle, hard-to-maintain code. Flexbox introduces a more intuitive, efficient, and powerful way to distribute space and align content within containers, whether those containers represent navigation bars, card grids, or entire page layouts.
The flexbox layout model is fundamentally one-dimensional, meaning it excels at arranging items in a single row or column at a time. This is in contrast to CSS Grid, which handles two-dimensional layouts (both rows and columns simultaneously). However, this one-dimensional focus makes flexbox perfect for components where you need precise control over alignment and distribution along a single axis--whether that is a horizontal row of navigation links or a vertical stack of card elements.
Understanding flexbox is essential for modern web development because it is supported across all major browsers and has become the go-to solution for component-level layout challenges. The specification was first proposed as a working draft in 2009 and has since evolved into a stable, widely-adopted standard that powers layouts on countless websites and applications. By mastering flexbox, developers gain a powerful tool for creating responsive, flexible, and maintainable user interfaces.
As noted in the MDN Web Docs, flexbox reached baseline status in September 2015, meaning it works reliably without prefixes or fallbacks in all modern browsers.
When to Use Flexbox
- Navigation components with evenly distributed items
- Card layouts that wrap responsively
- Media objects with image-text combinations
- Any layout requiring dynamic content adaptation
What This Guide Covers
This comprehensive reference guide systematically covers every aspect of the flexbox layout system. You will learn about the conceptual framework of axes and directions, master each property available to containers and items, and see practical examples demonstrating how to apply these concepts in real-world situations. Whether you are new to flexbox or looking to deepen your understanding of advanced techniques, this guide provides the information you need to leverage flexbox effectively in your projects.
The Two Axes of Flexbox
Understanding the concept of axes is fundamental to working with flexbox. Every flex layout operates along two perpendicular axes: the main axis and the cross axis. The main axis defines the primary direction in which flex items are arranged, while the cross axis runs perpendicular to it. Everything you do with flexbox--whether setting alignment, controlling wrapping, or adjusting item sizing--revolves around how these two axes interact.
The Main Axis
The main axis is the primary axis along which flex items are laid out within a flex container. The direction of this axis is determined by the flex-direction property, which accepts four values: row, row-reverse, column, and column-reverse. When flex-direction is set to row (the default), the main axis runs horizontally from left to right in left-to-right languages. When set to column, the main axis runs vertically from top to bottom.
Visual: Diagram showing the main axis direction for each flex-direction value, with arrows indicating the start and end points of the axis.
When you set flex-direction: row, the main axis runs from the left edge of the container toward the right edge. Items are placed starting from the main-start edge and continue toward the main-end edge. If you set flex-direction: column, the main axis runs from the top edge toward the bottom edge, with items placed from main-start to main-end. Understanding this distinction is crucial because many flexbox properties behave differently depending on which axis is the main axis.
The Cross Axis
The cross axis runs perpendicular to the main axis. If your main axis is horizontal (when using flex-direction: row), then your cross axis is vertical, running from the top of the container to the bottom. If your main axis is vertical (when using flex-direction: column), then your cross axis is horizontal, running from left to right.
Visual: Diagram showing the cross axis in relation to the main axis for both row and column directions.
This perpendicular relationship between the axes means that properties controlling alignment along one axis will affect the other axis when you change the flex-direction. For example, justify-content controls alignment along the main axis, while align-items controls alignment along the cross axis. When you switch to column direction, these properties essentially swap roles--justify-content now works vertically, and align-items works horizontally.
Start and End Lines
Flexbox follows a writing-mode-aware approach to layout, which means it adapts to different text directions and writing modes. Rather than thinking in terms of left, right, top, and bottom, flexbox conceptualizes layout in terms of start and end lines that correspond to the document's writing mode.
In English, which uses a left-to-right, top-to-bottom writing mode, the main-start edge is the left edge of the container, and the main-end edge is the right edge. The cross-start edge is the top, and the cross-end edge is the bottom. However, in Arabic, which uses a right-to-left writing mode, the main-start edge would be the right side of the container, and the main-end edge would be the left side.
This design decision ensures that flexbox works correctly with international content and different writing modes without requiring separate stylesheets or media queries. When you use flexbox properties, they always refer to the logical start and end of the container rather than physical directions, making your layouts more adaptable to different languages and text directions.
The Flex Container
A flex container is any element that has its display property set to flex or inline-flex. When you apply this display value to an element, all of its direct children become flex items and are laid out according to the flexbox formatting context. This is a significant departure from the normal document flow, where elements typically stack vertically or position themselves according to their display type.
Creating a Flex Container
To create a flex container, you use one of two display values. The display: flex declaration creates a block-level flex container that behaves similarly to a block element--it takes up the full available width and creates a new block formatting context. The display: inline-flex declaration creates an inline-level flex container that behaves similarly to an inline element--it only takes up as much width as necessary and does not create a new block formatting context.
/* Block-level flex container */
.container {
display: flex;
}
/* Inline-level flex container */
.container-inline {
display: inline-flex;
}
The choice between flex and inline-flex depends on your layout requirements. Use flex when you want the container to behave like a block element, stacking vertically with other block-level elements and taking up the full available width. Use inline-flex when you want the container to behave like an inline element, flowing with surrounding text and only taking up as much space as its content requires.
Initial Values and Default Behavior
When you create a flex container, it comes with a set of predefined initial values that determine how its flex items behave. According to the MDN Flex Property Reference, understanding these defaults is crucial because they explain why flex containers behave the way they do even before you apply any additional styles.
By default, flex-direction is set to row, meaning items are arranged horizontally in a single row from left to right. The flex-wrap property defaults to nowrap, meaning items will not wrap to additional lines even if they overflow the container. The justify-content property defaults to flex-start, meaning items are aligned to the start of the main axis. The align-items property defaults to stretch, meaning items stretch along the cross axis to fill the container's height (for row direction) or width (for column direction).
Each flex item has its own set of initial values. flex-grow defaults to 0, meaning items will not grow to fill available space. flex-shrink defaults to 1, meaning items will shrink if necessary to prevent overflow. flex-basis defaults to auto, meaning the item's size is determined by its content or explicit width/height properties. The align-self property defaults to auto, meaning the item inherits the align-items value from its container.
| Property | Default Value | Effect |
|---|---|---|
| flex-direction | row | Items arrange horizontally |
| flex-wrap | nowrap | No wrapping to new lines |
| justify-content | flex-start | Items align to start of main axis |
| align-items | stretch | Items stretch along cross axis |
| Item Property | Default Value | Effect |
|---|---|---|
| flex-grow | 0 | Items do not grow |
| flex-shrink | 1 | Items shrink if needed |
| flex-basis | auto | Size based on content or explicit dimensions |
The combination of these initial values produces a layout where items display in a single row, using their content size as their base size, stretching to fill the container's cross dimension, and shrinking if necessary to fit within the container. This default behavior is intentional and often serves as a good starting point for customization.
| Property | Values | Description |
|---|---|---|
| flex-direction | row | row-reverse | column | column-reverse | Sets main axis direction |
| flex-wrap | nowrap | wrap | wrap-reverse | Controls single/multi-line behavior |
| flex-flow | <flex-direction> <flex-wrap> | Shorthand for direction and wrap |
| justify-content | flex-start | flex-end | center | space-between | space-around | space-evenly | Aligns items along main axis |
| align-items | stretch | flex-start | flex-end | center | baseline | Aligns items along cross axis |
| align-content | flex-start | flex-end | center | space-between | space-around | stretch | Aligns lines in multi-line containers |
Container Properties in Practice
Understanding each property in isolation is valuable, but seeing how they work in practice brings the concepts to life. The following examples demonstrate the practical application of flex container properties.
flex-direction Examples
/* Items flow left to right (default) */
.row { flex-direction: row; }
/* Items flow right to left */
.row-reverse { flex-direction: row-reverse; }
/* Items flow top to bottom */
.column { flex-direction: column; }
/* Items flow bottom to top */
.column-reverse { flex-direction: column-reverse; }
Visual: When applied to a container with three child elements, row displays items as [1][2][3], row-reverse displays them as [3][2][1], column displays them vertically as 1 above 2 above 3, and column-reverse displays them as 3 above 2 above 1.
justify-content Values
The justify-content property defines how the browser distributes space between and around flex items along the main axis of the container. This property takes effect when there is positive space available in the container.
flex-start: Pack toward start of main axis--items cluster at the left edge (for row) or top edge (for column)flex-end: Pack toward end of main axis--items cluster at the right edge (for row) or bottom edge (for column)center: Center within container--items group together in the middle of the containerspace-between: Even distribution, first/last at edges--no space before the first item or after the last itemspace-around: Even distribution with half-size spaces at ends--each item has equal space on both sides, but the edge items have half the space of inner itemsspace-evenly: Equal spacing throughout--space between all items (and at edges) is perfectly equal
Visual: A comparison showing six rows of items, each demonstrating how the items shift position with each justify-content value. Notice how space-between pushes items to the edges, space-around creates breathing room but keeps items from touching edges, and space-evenly creates uniform spacing including at the container boundaries.
align-items Values
The align-items property defines how flex items are aligned along the cross axis of the flex container. Unlike justify-content, which deals with space distribution along the main axis, align-items deals with perpendicular alignment.
stretch(default): Stretch to fill container--items extend to match the tallest/fwidest item in the rowflex-start: Align at cross axis start--items cluster at the top edge (for row) or left edge (for column)flex-end: Align at cross axis end--items cluster at the bottom edge (for row) or right edge (for column)center: Center along cross axis--items group together in the middle of the containerbaseline: Align along text baseline--items align based on their text content, which may result in visual misalignment if items have different font sizes or padding
Visual: A comparison showing five rows of items of varying heights, demonstrating how each align-items value positions the items differently within the container. Pay special attention to how baseline can create unexpected visual results when items have different content.
align-content Values
The align-content property is similar to justify-content but operates along the cross axis. Crucially, this property only takes effect when the flex container is multi-line (when flex-wrap is set to wrap or wrap-reverse). In single-line containers, align-content has no effect.
flex-start: Pack lines toward start of cross axis--all lines group at the topflex-end: Pack lines toward end of cross axis--all lines group at the bottomcenter: Center lines within container--all lines group in the middlespace-between: First line at start, last at end--lines distribute evenly with equal space betweenspace-around: Lines distribute with equal space around each--half-size space at top and bottomstretch(default): Stretch lines to fill remaining space--lines expand to fill available vertical space
Visual: A wrapped flex container with multiple lines of items, showing how each align-content value positions the entire group of lines within the container. For advanced CSS layouts that combine flexbox with other modern techniques, understanding these properties is essential for creating sophisticated, responsive interfaces.
Flex Item Properties
While container properties control the overall layout, flex item properties control how individual items behave within that layout. These properties determine how items grow, shrink, and are sized within the flex container.
flex-grow
The flex-grow property specifies the flex grow factor, which determines how much a flex item will grow relative to the other flex items in the container when positive free space is distributed. The default value is 0, meaning items will not grow to fill available space.
.item {
flex-grow: 0; /* Default - do not grow */
flex-grow: 1; /* Grow equally with siblings */
flex-grow: 2; /* Grow twice as much as siblings */
}
This property accepts a unitless number that serves as a proportion. If all items have flex-grow: 1, they will each receive an equal amount of available space. If one item has flex-grow: 2 while others have flex-grow: 1, that item will receive twice as much of the available space as the others.
Visual: A container with 500px available width and three items, each with flex-basis: 0. With flex-grow: 1 on all items, each receives approximately 167px. If one item has flex-grow: 2, it receives about 200px while the others receive about 150px each.
Understanding flex-grow is key to creating flexible layouts that adapt to available space. A common pattern is setting flex-grow: 1 on content areas to make them fill remaining space while sidebar elements maintain fixed widths.
flex-shrink
The flex-shrink property specifies the flex shrink factor, which determines how much a flex item will shrink relative to the other flex items in the container when there is not enough positive free space. The default value is 1, meaning items will shrink equally to prevent overflow.
.item {
flex-shrink: 1; /* Default - shrink as needed */
flex-shrink: 0; /* Never shrink - maintain full size */
flex-shrink: 2; /* Shrink twice as much as siblings */
}
Like flex-grow, this property accepts a unitless proportion. A value of 0 prevents the item from shrinking, which is useful for items that must maintain their full size even when space is constrained. Higher values make items shrink more aggressively relative to their siblings.
Visual: A container with 300px width containing three items with flex-basis: 150px. Without wrapping, the items must fit within 300px. With flex-shrink: 1 on all items, each shrinks to 100px. If one item has flex-shrink: 0, it stays at 150px while the other two shrink to 75px each.
flex-basis
The flex-basis property specifies the initial main size of a flex item before any growing or shrinking occurs. It accepts various values including length units (px, em, rem, %), the keyword auto (default), and the keyword content.
.item {
flex-basis: auto; /* Default - use width/height or content */
flex-basis: 200px; /* Fixed initial size */
flex-basis: 50%; /* Percentage of container */
flex-basis: 0; /* Zero-based sizing for proportional distribution */
}
When flex-basis is set to auto, the browser uses the item's width property (for row direction) or height property (for column direction) as the basis. If neither is specified, the basis is determined by the item's content size. When flex-basis is set to a specific length unit, that value becomes the item's initial size regardless of any explicit width or height.
A critical nuance is the difference between flex-basis: 0 and flex-basis: 0%. Historically, some browsers treated missing flex-basis values in the shorthand as 0% rather than 0, which could affect layout calculations. Modern browsers have largely converged, but this historical quirk demonstrates why testing across browsers remains important.
The flex Shorthand
The flex property is a shorthand that combines flex-grow, flex-shrink, and flex-basis into a single property declaration. As documented in the MDN Flex Property Reference, using the shorthand is recommended because it provides cleaner code and handles default values correctly.
Syntax
/* One value: flex-grow only */
flex: 1;
/* Two values: flex-grow | flex-shrink OR flex-grow | flex-basis */
flex: 1 1 auto;
flex: 1 200px;
/* Three values: flex-grow | flex-shrink | flex-basis */
flex: 1 1 200px;
With a single value, if it's a unitless number, it sets flex-grow to that value with defaults of 1 and 0% for shrink and basis. If it's a keyword like auto, initial, or none, it sets specific combinations. With two values, the first is always flex-grow, and the second is either flex-shrink (unitless number) or flex-basis (length unit). With three values, they set flex-grow, flex-shrink, and flex-basis in that order.
Common Shorthand Values
| Value | Equivalent | Use Case |
|---|---|---|
flex: 0 0 auto | none | Fixed size, no flexibility |
flex: 1 | 1 1 0% | Proportional equal sizing |
flex: auto | 1 1 auto | Full flexibility, content-based sizing |
flex: initial | 0 1 auto | Default behavior |
Prefer the flex shorthand over individual flex-grow, flex-shrink, and flex-basis declarations. The shorthand is more concise, handles default values correctly, and makes your intentions clearer.
align-self Property
The align-self property allows the default alignment (or the one specified by align-items on the container) to be overridden for individual flex items. This is particularly useful when you want most items to follow the container's alignment rule but need one or more items to be aligned differently.
.item {
align-self: auto; /* Inherit from container */
align-self: flex-start; /* Override to start */
align-self: center; /* Override to center */
align-self: stretch; /* Override to stretch */
}
The align-self property accepts the same values as align-items: auto, flex-start, flex-end, center, baseline, and stretch. The auto value (default) means the item inherits the container's align-items value.
A common use case for align-self is creating a list of items where one item should be aligned differently--for example, a navigation bar where one link needs to appear on the opposite side of the container.
Browser Quirks and Notes
When working with the flex shorthand, be aware of a few historical browser quirks. Internet Explorer 11 has known issues with flexbox, including incorrect handling of flex-basis values and problems with min-height in certain scenarios. If you need to support IE11, thorough testing and potentially fallback styles are necessary.
Additionally, when using flex-basis: auto with percentage widths, some older browsers may calculate sizes incorrectly. The safest approach for maximum compatibility is to be explicit about your sizing strategy and test across target browsers.
Practical Layout Patterns
Understanding individual properties is essential, but seeing how they combine to create common layouts demonstrates the real power of flexbox. These patterns appear frequently in web development and represent starting points you can adapt for your own projects.
Centering Content
One of the most common layout requirements is centering content both horizontally and vertically within a container. This was historically challenging, requiring workarounds like absolute positioning or table displays. With flexbox, it becomes straightforward.
The technique combines justify-content: center and align-items: center on the container. For horizontal centering along the main axis, use justify-content: center. For vertical centering along the cross axis, use align-items: center. Together, they perfectly center the content.
<div class="centered">
<div class="content">
<h1>Welcome</h1>
<p>This content is perfectly centered.</p>
</div>
</div>
.centered {
display: flex;
justify-content: center; /* Horizontal centering */
align-items: center; /* Vertical centering */
min-height: 400px; /* Container must have height */
}
Visual: A container with a visible border showing content positioned exactly in the center, both horizontally and vertically.
This pattern works regardless of whether the flex direction is row or column, making it equally effective for horizontally-oriented and vertically-oriented layouts.
Navigation Bar
Navigation bars are among the most common flexbox use cases. A typical navigation might have a logo on the left, links in the center or right, and perhaps a call-to-action button. Flexbox makes this layout intuitive and responsive.
<nav class="navbar">
<div class="logo">MyBrand</div>
<ul class="nav-links">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/services">Services</a></li>
</ul>
<a href="/contact" class="cta">Contact</a>
</nav>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 1rem;
height: 60px;
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.nav-links {
display: flex;
gap: 2rem;
list-style: none;
margin: 0;
padding: 0;
}
.cta {
padding: 0.5rem 1rem;
background: #0066cc;
color: white;
border-radius: 4px;
}
Visual: A horizontal navigation bar with a logo on the left, evenly spaced links in the center-right area, and a styled button on the far right.
For responsive designs, you might change the flex-direction to column on smaller screens using a media query, creating a mobile-friendly stacked navigation.
Card Grid
Card-based layouts, whether for product displays, blog post previews, or dashboard widgets, benefit greatly from flexbox's ability to handle wrapping and equal-height items.
<div class="card-grid">
<article class="card">...</article>
<article class="card">...</article>
<article class="card">...</article>
<article class="card">...</article>
</div>
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
padding: 1.5rem;
}
.card {
flex: 1 0 280px; /* Grow, don't shrink, 280px minimum */
max-width: 400px; /* Optional maximum width */
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
Visual: A grid of cards that wraps responsively. On wide screens, four cards appear in a row. As the screen narrows, cards wrap to new lines. All cards have equal height regardless of content length.
This pattern automatically adjusts to available space. As the container width changes, cards wrap to new lines, and the flex properties ensure they maintain appropriate sizes without requiring multiple breakpoints.
Media Object
The media object pattern--where an image or avatar sits next to text content--appears throughout web interfaces, from comment sections to chat interfaces to notification systems.
<div class="media-object">
<img src="avatar.jpg" alt="User avatar" class="media-image">
<div class="media-content">
<h3>Jane Doe</h3>
<p>Software Engineer</p>
</div>
</div>
.media-object {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.media-image {
width: 64px;
height: 64px;
flex-shrink: 0; /* Prevent squishing */
border-radius: 50%;
}
.media-content {
flex: 1; /* Fill remaining space */
}
Visual: A circular avatar image on the left with the user's name and title text on the right. The image maintains its size regardless of how much text content exists.
This approach ensures the image maintains its size while the content area adjusts to fill the remaining horizontal space, regardless of which element appears first in the source order.
For more on modern layout techniques, see our guide on Creating Responsive Web Layouts With Css Grid and learn how flexbox and grid work together to create sophisticated responsive web designs.
Common Layout Problems and Solutions
Even experienced developers encounter challenges when working with flexbox. Understanding these common pitfalls and their solutions helps you write more robust layouts.
Items Not Wrapping
A frequent issue is items refusing to wrap even when they clearly don't fit in the container. This usually happens because flex-wrap: nowrap is the default, and the items are shrinking to fit rather than wrapping.
.container {
display: flex;
flex-wrap: wrap; /* Explicitly enable wrapping */
}
To fix this, explicitly set flex-wrap: wrap on the container. If items are still shrinking too much, check their flex-shrink values (which default to 1) and increase their flex-basis or min-width to prevent excessive shrinking.
Alignment Not Working
When justify-content or align-items doesn't seem to have any effect, the most common cause is that there isn't enough positive free space in the container. These properties distribute existing space; they cannot create space out of nothing.
If you want items centered but they appear at the start, check whether the container is actually larger than its content. You can test this by temporarily adding a background color to the container to visualize its boundaries.
Item Sizes Not as Expected
Confusion about flex-basis versus width and height is common. Remember that flex-basis takes precedence over width and height when they are in the same direction as the flex container. Setting width: 200px on an item in a row-direction container may not have the expected effect if flex-basis is set differently.
When in doubt, use the browser's developer tools to inspect the computed flex values and understand how they are being applied.
Vertical Centering in Column Direction
When using flex-direction: column, you might find that justify-content: center works to center items vertically (because the main axis is now vertical), but align-items: center centers horizontally. If you want both horizontal and vertical centering in column direction, you need both properties active.
.column-center {
flex-direction: column;
justify-content: center; /* Now works vertically */
align-items: center; /* Now works horizontally */
}
Equal Height Items Not Working
Flexbox items stretch along the cross axis by default (align-items: stretch), which should automatically create equal-height items in a row. If items aren't equal height, check for the following issues:
- An explicit
heightoralign-selfvalue is overriding the stretch behavior - The container has
align-itemsset to something other thanstretch - Items are in a single-line container without the stretch behavior active
Gaps Not Working in Older Browsers
The gap property for flex containers has excellent support in modern browsers, but older browsers (particularly Safari versions before 14 and IE) do not support it. For maximum compatibility, use margins with :first-child pseudo-elements or CSS logical properties.
.container {
display: flex;
flex-wrap: wrap;
margin: -0.5rem; /* Negative margin to offset gap */
}
.container > * {
margin: 0.5rem; /* Actual gap */
}
For more debugging techniques, see our guide on Creating Better CSS Forms which covers common layout debugging strategies and web design best practices.
Browser Compatibility
Flexbox has excellent browser support across all modern browsers, making it safe to use in production websites.
As documented by MDN Web Docs, flexbox reached baseline status in September 2015, meaning it works reliably without prefixes or fallbacks in all modern browsers.
| Browser | Version | Release Date |
|---|---|---|
| Chrome | 29+ | August 2013 |
| Firefox | 28+ | March 2014 |
| Safari | 9+ | September 2015 |
| Edge | 12+ | July 2015 |
| Opera | 17+ | August 2013 |
Current Support
As of the current browser versions, flexbox is supported in Chrome, Firefox, Safari, Edge, and Opera, including their mobile counterparts. The support extends to older browser versions from around 2017 or earlier, depending on the specific property.
Internet Explorer 11 Note
Internet Explorer 11 has partial and buggy flexbox support:
- Incorrect handling of
flex-basisvalues - Problems with
min-heightin certain scenarios - Incomplete support for
flex-wrap - The
flexshorthand may not behave as expected with all value combinations
If IE11 support is required, thorough testing and fallback styles are necessary. Consider using feature detection with @supports to provide alternative layouts for unsupported browsers.
Testing Recommendations
When developing with flexbox, test your layouts across multiple browsers and screen sizes. While the core functionality is consistent, subtle rendering differences can occur, particularly with complex alignment scenarios or when combining flexbox with other layout methods.
Use browser developer tools to inspect flex layouts--the Firefox and Chrome dev tools have dedicated flexbox debugging tools that visualize flex containers and their properties, making it easier to understand unexpected behavior.
For comprehensive testing:
- Test layouts across Chrome, Firefox, Safari, and Edge
- Verify on mobile browsers (iOS Safari, Chrome for Android)
- Use browser dev tools to visualize flex container boundaries
- Check layouts at multiple viewport sizes, not just breakpoints
Best Practices
Following established best practices helps you write maintainable flexbox code and avoid common pitfalls.
Use the Shorthand
Prefer the flex shorthand over individual flex-grow, flex-shrink, and flex-basis declarations. The shorthand is more concise, handles default values correctly, and makes your intentions clearer. For most cases, flex: 1 or flex: auto provides the flexibility you need without verbose declarations.
/* Preferred */
.item { flex: 1; }
/* Verbose and unnecessary */
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
Be Explicit with Directions
Even though row is the default for flex-direction, explicitly declaring it makes your code clearer and signals intent to future maintainers. Similarly, explicitly declaring flex-wrap helps developers understand the expected wrapping behavior without having to remember defaults.
.container {
display: flex;
flex-direction: row; /* Explicit is clearer */
flex-wrap: nowrap; /* Explicit is clearer */
}
Consider Mobile First
Design your flexbox layouts with mobile constraints in mind first, then enhance for larger screens using media queries. Flexbox's flexible nature makes it well-suited to responsive design, but starting with the most constrained viewport helps ensure your layouts work everywhere.
Use Gap for Spacing
The gap property (and its row-gap and column-gap variants) provides a cleaner way to add spacing between flex items than using margins. gap creates consistent spacing without requiring calculation to handle first or last items differently.
.container {
display: flex;
flex-wrap: wrap;
gap: 1rem; /* Cleaner than margin calculations */
}
Performance Considerations
- Flexbox performs well for most use cases and is GPU-accelerated in modern browsers
- Avoid nesting excessive flex containers, which can create complex layout thrashing
- Use
will-change: transformsparingly for animated flex items - Test on lower-end devices to ensure smooth performance, particularly for animated layouts
Combine with CSS Grid Strategically
Flexbox and CSS Grid complement each other. Use CSS Grid for page-level layouts and main structural areas, and flexbox for component-level layouts within those areas. This combination typically provides the best balance of flexibility and control.
For more on combining layout techniques, see our guide on Creating Responsive Web Layouts With Css Grid.
Debugging Tips
When layouts don't behave as expected:
- Use browser dev tools to visualize the flex container
- Check computed styles to see what values are actually applied
- Verify there is enough positive space for alignment properties to work
- Confirm
flex-basisisn't overriding explicit width/height values - Check for
min-widthormin-heightconstraints that prevent expected behavior
Frequently Asked Questions
When should I use flexbox vs. CSS Grid?
Use flexbox for one-dimensional layouts (single row or column) where you need precise control over alignment and distribution. Use CSS Grid for two-dimensional layouts (rows AND columns) where you need to position items in specific grid cells. Many layouts use both--Grid for page structure and flexbox for component layout within those areas.
What is the difference between justify-content and align-items?
justify-content aligns items along the main axis (the direction set by flex-direction). align-items aligns items along the cross axis (perpendicular to the main axis). In row direction, justify-content works horizontally and align-items works vertically. In column direction, these reverse.
How do I prevent flex items from shrinking?
Set flex-shrink to 0 on the items that should not shrink: flex: 0 0 <basis>. For example, flex: 0 0 200px prevents the item from shrinking below 200px width.
Why is my flex-basis being ignored?
flex-basis takes precedence over explicit width/height in the flex direction. If you want the width/height property to control sizing, use flex-basis: auto. Also ensure there is enough space in the container for the basis to be respected.
Can I use flexbox for entire page layouts?
Yes, but consider using CSS Grid for the main page structure (header, sidebar, main content, footer) and flexbox for component-level layouts within those areas. This combination typically provides the best balance of flexibility and control.
How do I create equal-height flex items?
Flexbox items stretch along the cross axis by default (align-items: stretch). This automatically creates equal-height items in a row. If items aren't equal height, check that no explicit height or align-self value is overriding the stretch behavior.
Sources
-
MDN Web Docs: Basic Concepts of Flexbox - Mozilla's authoritative documentation covering the foundational concepts of flexbox including the two-axis model, flex containers, and initial values
-
MDN Web Docs: Flex Property Reference - Comprehensive technical reference for the flex shorthand property, including syntax variations, constituent properties, and browser compatibility
-
GeeksforGeeks: Complete Guide to Flexbox - Practical tutorial-style guide covering flexbox as a one-dimensional layout method for aligning and distributing space among items