Complete CSS Flexbox Guide: Master Flexible Layout in 2026

12 min read

Learn CSS Flexbox from scratch. Container properties (display flex, direction, wrap, justify, align), item properties (grow, shrink, basis), common patterns like centering, navbar, card grid, and the holy grail layout.

What is CSS Flexbox and why you should master it

CSS Flexbox (Flexible Box Layout Module) is a one-dimensional layout model that efficiently distributes space and aligns elements within a container, even when their sizes are unknown or dynamic. It was specifically designed to solve the historical CSS layout problems that previously required hacks with floats, tables, or position absolute.

Since its standardization in 2017 and universal adoption by all modern browsers, Flexbox has become an essential tool for any frontend developer. Unlike older methods, Flexbox works predictably, responds well to different screen sizes, and dramatically reduces the amount of CSS needed for common layouts.

Problems that Flexbox elegantly solves:

  • Vertical centering: Before Flexbox, vertically centering an element required tricks like translateY(-50%) or CSS tables. With Flexbox it is a single property
  • Equal distribution: Distributing space between elements equally or proportionally without manual calculations
  • Visual order: Changing the order of elements on screen without altering the HTML
  • Responsive without media queries: Flex items can automatically shrink, grow, and wrap
  • Consistent alignment: Aligning elements vertically and horizontally with a coherent syntax

In this guide we cover all Flexbox properties with practical examples. If you want to experiment as you read, open our Flexbox playground in another tab to try each property in real time.

The flex container: display flex and the main axis

Everything in Flexbox starts by declaring a container as display: flex (or display: inline-flex if you want the container to behave as an inline element). When you do this, all direct children automatically become flex items.

Default behavior of display: flex:

  • Children are placed in a horizontal row (flex-direction: row)
  • Children do NOT wrap to the next line (flex-wrap: nowrap)
  • Children are aligned to the start of the main axis (justify-content: flex-start)
  • Children stretch to fill the container height (align-items: stretch)

flex-direction defines the main axis of the container:

ValueMain axisDirection
row (default)HorizontalLeft to right (in LTR languages)
row-reverseHorizontalRight to left
columnVerticalTop to bottom
column-reverseVerticalBottom to top

It is fundamental to understand that Flexbox works with two axes: the main axis (defined by flex-direction) and the cross axis (perpendicular to the main axis). All alignment properties refer to these axes, not to fixed "horizontal" or "vertical" directions.

flex-wrap controls whether items wrap:

  • nowrap (default): All items on a single line, even if they compress
  • wrap: Items move to the next line when they do not fit
  • wrap-reverse: Same as wrap but lines stack in reverse order

The flex-flow shorthand combines both properties: flex-flow: row wrap; is equivalent to declaring flex-direction: row; and flex-wrap: wrap; separately.

Alignment properties: justify-content and align-items

Alignment properties are the heart of Flexbox. justify-content aligns items along the main axis, while align-items aligns them along the cross axis.

justify-content (main axis alignment):

ValueBehavior
flex-startItems grouped at the start of the main axis
flex-endItems grouped at the end of the main axis
centerItems centered on the main axis
space-betweenFirst item at start, last at end, equal space between the rest
space-aroundEqual space around each item (edges have half the space)
space-evenlyIdentical space between all items and the container edges

align-items (cross axis alignment):

ValueBehavior
stretch (default)Items stretch to fill the entire cross axis
flex-startItems aligned to the start of the cross axis
flex-endItems aligned to the end of the cross axis
centerItems centered on the cross axis
baselineItems aligned by their text baseline

align-content (only with flex-wrap: wrap):

When there are multiple lines of flex items, align-content controls how those lines are distributed along the cross axis. It accepts the same values as justify-content plus stretch. It only has effect when there is more than one line of items.

gap (spacing between items):

The gap property (formerly grid-gap) sets the space between flex items without using margins. It accepts one or two values: gap: 16px; applies 16px in both directions, gap: 16px 24px; applies 16px vertically and 24px horizontally. It is the cleanest way to space elements and avoids the edge margin problem.

Flex item properties: grow, shrink, and basis

Flex item properties control how each individual element occupies the available space within the flex container. They are the key to creating truly flexible layouts.

flex-grow (growth factor):

Defines how much remaining space an item should take in proportion to others. The default value is 0 (does not grow). If all items have flex-grow: 1, they all grow equally. If one item has flex-grow: 2 and the others flex-grow: 1, the first will receive double the remaining space.

  • flex-grow: 0 - The item does NOT grow beyond its base size
  • flex-grow: 1 - The item takes its proportional share of remaining space
  • flex-grow: 2 - The item takes double the remaining space of an item with flex-grow: 1

flex-shrink (shrink factor):

Defines how much an item shrinks when space is insufficient. The default value is 1 (all items shrink proportionally). If an item has flex-shrink: 0, it will never shrink below its base size, which is useful for fixed-size elements like icons or logos.

flex-basis (base size):

Defines the initial size of the item before remaining space is distributed. Accepts length values (200px, 30%) or auto (default, uses the item's width or height). It is more predictable than width/height for flex items because it is calculated in the context of the main axis.

The flex shorthand:

The flex property combines grow, shrink, and basis in a single declaration:

  • flex: 1; equals flex: 1 1 0%; (grows, shrinks, base size 0)
  • flex: auto; equals flex: 1 1 auto; (grows, shrinks, automatic base size)
  • flex: none; equals flex: 0 0 auto; (no grow, no shrink, fixed size)
  • flex: 0 0 250px; creates an item of exactly 250px that does not change size

align-self allows an individual item to override the container's cross-axis alignment. It accepts the same values as align-items. And the order property changes the visual order of an item without modifying the HTML (default: 0, negative values go first).

Common patterns: centering, navbar, and sticky footer

Flexbox shines in the most common layout patterns in web development. These are the ones you will use in practically every project:

Pattern 1: Perfect centering (vertical and horizontal)

The most searched CSS pattern. With Flexbox it takes 3 lines:

  • display: flex;
  • justify-content: center;
  • align-items: center;

This centers any child element both horizontally and vertically, regardless of its dimensions. It works for text, images, modals, loading spinners, error pages, anything.

Pattern 2: Navbar with logo on the left and menu on the right

The typical navigation bar layout:

  • Nav container: display: flex; justify-content: space-between; align-items: center;
  • The logo stays on the left automatically
  • Menu links group to the right
  • Everything is vertically centered effortlessly

Pattern 3: Sticky footer at the bottom of the page

A footer that always stays at the bottom, even when content is short:

  • Body or wrapper: display: flex; flex-direction: column; min-height: 100vh;
  • Main content: flex: 1; (takes all available space)
  • The footer stays at the natural bottom or gets pushed down

Pattern 4: Item list with the last one aligned right

For example, a breadcrumb or a row of buttons where the last one goes to the end:

  • Container: display: flex; align-items: center;
  • Last item: margin-left: auto;
  • Auto margin in Flexbox absorbs all available space, pushing the item to the opposite end

Pattern 5: Sidebar + main content

  • Container: display: flex;
  • Sidebar: flex: 0 0 280px; (fixed width of 280px)
  • Content: flex: 1; (takes all remaining space)

Experiment with these patterns in our Flexbox playground to see them work in real time.

Responsive card grid and holy grail layout

Flexbox is excellent for creating responsive card layouts and the classic "holy grail layout" (header, footer, sidebar, and main content).

Responsive card grid with flex-wrap:

The most common pattern for displaying product cards, blog articles, or any collection of elements:

  • Container: display: flex; flex-wrap: wrap; gap: 24px;
  • Each card: flex: 1 1 300px; (minimum 300px wide, grows to fill the space)
  • Cards distribute automatically: 3 per row on large screens, 2 on medium, 1 on mobile

A common problem with this pattern: if the last row has fewer items than the others, they grow to fill the entire row. To avoid this, use flex: 0 1 calc(33.333% - 16px); with a max-width, or switch to CSS Grid for that specific situation.

Holy grail layout (the perfect layout):

The "holy grail" of web design: fixed header at top, fixed footer at bottom, left sidebar, right sidebar, and main content in the center:

  • Outer wrapper: display: flex; flex-direction: column; min-height: 100vh;
  • Header: automatic size
  • Middle section: display: flex; flex: 1;
  • Left sidebar: flex: 0 0 200px;
  • Main content: flex: 1;
  • Right sidebar: flex: 0 0 200px;
  • Footer: automatic size

This layout is 100% responsive: on small screens, you can change the middle section to flex-direction: column; with a media query to stack the sidebars below the content.

Equal height cards:

An automatic benefit of Flexbox: all items in a row have the same height by default (align-items: stretch). This means cards in the same row will always have the same height, regardless of how much content each one has. If you also need the button in each card to stick to the bottom, apply flex-direction: column to the card content and margin-top: auto; to the button.

Flexbox vs CSS Grid: when to use each one

The question every developer asks: if I already have Flexbox, do I need CSS Grid? And vice versa. The answer is that they are not competitors, they are complementary. Each one has scenarios where it is the best choice.

Use Flexbox when:

  • The layout is one-dimensional (a row OR a column, not both at once)
  • You need items to dynamically adapt to the available space
  • The content should dictate the size of the elements
  • You need to align elements within a component (navbar, card, toolbar, form)
  • You want items to naturally wrap without defining explicit rows/columns

Use CSS Grid when:

  • The layout is two-dimensional (you need to control rows AND columns simultaneously)
  • You have a defined grid structure with named areas
  • The layout should dictate the size of the content (not the other way around)
  • You need to place items at specific positions in the grid
  • You want items to span multiple rows or columns

Direct comparison:

FeatureFlexboxCSS Grid
Dimensionality1D (row or column)2D (rows and columns)
ApproachContent outwardLayout inward
AlignmentExcellent on one axisExcellent on both axes
ResponsiveAutomatic with wrapRequires media queries or auto-fill
ComplexityLower learning curveMore power, more complexity

In practice, the best layouts combine both: CSS Grid for the overall page structure (header, sidebar, main, footer) and Flexbox for the internal alignment of each component (navbar items, card content, form buttons). Try both with our Flexbox playground and our CSS Grid generator.

Common mistakes and advanced Flexbox tips

Even experienced developers make mistakes with Flexbox. Here are the most frequent ones and how to avoid them:

Mistake 1: Forgetting that flex-shrink defaults to 1

Flex items shrink by default. If an item has a fixed width that must be respected (like a 48px icon), you need flex-shrink: 0; explicitly. Without this, the item can compress below its expected size when space is insufficient.

Mistake 2: Using width instead of flex-basis

While width works in most cases, flex-basis is more predictable within a flex context. flex-basis: 300px; establishes the size on the main axis regardless of whether it is horizontal or vertical.

Mistake 3: Not using min-width: 0 for truncated text

Flex items have min-width: auto by default, which prevents them from shrinking below their content size. If you need to truncate text with text-overflow: ellipsis inside a flex item, add min-width: 0; to the item to allow compression.

Mistake 4: Trying to create complex grids with Flexbox alone

Flexbox was not designed for complex two-dimensional layouts. If you need items to align in rows AND columns simultaneously, CSS Grid is the right tool.

Advanced tips:

  • margin: auto on flex items: Absorbs all available space in the given direction. margin-left: auto; pushes an item to the right. margin: auto; perfectly centers an item
  • flex-basis: 0 vs auto: With flex: 1 1 0% all items have the same base size (distributed equally). With flex: 1 1 auto the base size depends on content (items with more text are wider)
  • Nested flex containers: A flex item can itself be a flex container. This is the foundation of complex layouts like dashboards and web applications
  • Accessibility and order: The order property changes visual order but NOT the screen reader reading order or Tab navigation. Use it carefully and never as a substitute for well-structured HTML

Practice and debug your flex layouts with our interactive Flexbox playground, where you can change each property and see the result instantly.

Try this tool:

Open tool

Frequently asked questions

What is the difference between justify-content and align-items?

justify-content aligns items along the main axis (horizontal by default with flex-direction: row), while align-items aligns them along the cross axis (vertical by default). If you change flex-direction to column, the roles swap: justify-content controls the vertical axis and align-items the horizontal.

What does flex: 1 do exactly?

flex: 1 is a shorthand that equals flex-grow: 1, flex-shrink: 1, flex-basis: 0%. It means the item will grow to take its proportional share of available space, will shrink if necessary, and its base size is 0 (all size comes from growth). If all items have flex: 1, they will share the space equally.

How do I center a div vertically and horizontally with Flexbox?

Apply to the parent container: display: flex; justify-content: center; align-items: center; and make sure the container has a defined height (for example, min-height: 100vh for full screen). These 3 properties center any child element on both axes.

Flexbox or Grid: which should I learn first?

Flexbox. It is simpler to learn, covers most component layout needs, and is used within CSS Grid. Once you master Flexbox, CSS Grid will be much easier to understand because they share concepts like gap, align-items, and justify-content. In professional practice you will use both: Grid for page structure and Flexbox for internal components.

Why are my flex items not wrapping to the next line?

The default value of flex-wrap is nowrap, which forces all items to stay on a single line even if they compress. To have items move to the next line when they do not fit, add flex-wrap: wrap; to the flex container. You can also use the shorthand flex-flow: row wrap;

Can I use Flexbox and CSS Grid together in the same project?

Yes, and it is in fact the recommended practice. Use CSS Grid for the overall page structure (defining areas like header, sidebar, main, footer) and Flexbox for internal component alignment (items inside the navbar, card content, form buttons). A Grid item can itself be a Flex container and vice versa.