The tool you need, ready to use

CSS Flexbox Playground

The container on the stage is a real Flexbox. Click direction, wrapping, alignment and gap and the items move at once; drag the corner handle to change the width and height and see when items wrap or shrink. Hatching is free space, dark bars are gap, and red hatching is overflow. Select an item and change values such as flex: 1, auto or none, and the size breakdown shows, in the spec's calculation order, how the free space was shared out and why an item stops shrinking. Copy the finished layout as CSS and HTML.

Last updated 2026-10-21All math stays in your browser
Items 4
Arrow keys ← and → change the width, ↑ and ↓ change the height, 10px at a time. Hold Shift for 50px steps. Home fits the width to the stage.

Container.container
Directionflex-direction
Wrappingflex-wrap
Main-axis alignmentjustify-content
Cross-axis alignmentalign-items
Multi-line alignmentalign-content
px
px
Selected item.item-1
Pick a flex valueflex: 0 1 auto

This item's cross-axis alignmentalign-self
Main-axis auto marginmargin
Size breakdownRecomputed in the order of spec §9.7 and checked against the browser's values

  
Example layoutsClick one to apply it to the stage

Last updated 2026-10-21Your inputs are not stored

ROBERIN standardThe tool you need,
ready to use.
  • Clear at a glanceInputs and results sit where you expect them.
  • Result firstThe key number comes first; the working only when you need it.
  • Ask lessNo sign-up and no unnecessary details.

A Flexbox playground that shows the free space

The container on the stage of this CSS Flexbox playground is a real display: flex box. Click the direction, wrapping, alignment and gap settings and the items move on the spot. Drag the corner handle to change the width and height, and you can see exactly when items wrap onto the next line and when they shrink. The guides draw the main and cross axes as arrows, gap as dark bars, and the free space no item occupies as hatching with a number. When an item pushes past the container, the overflow is shown as red hatching.

Select an item and change its flex: 1, auto or none value, and the size breakdown below follows the calculation order of the CSS Flexbox spec (§9.7) to show how the free space was shared out. That result is checked, to within 1px, against the sizes your browser actually drew. When the layout looks right, copy the CSS and HTML, or copy a link that stores the current state in the address.

When to use Flexbox, and how it differs from Grid

Flexbox lays items out along one direction and shares space within that line. Even when it wraps onto several lines, each line works out its space separately, so the column edges of one line do not match those of the next. For layouts where rows and columns must line up, like a table, CSS Grid is the better fit.

  • Menus and button groups: items of different lengths sit on one line with equal spacing from gap. To push a single item to the end, give it an auto margin (see the 'Navigation bar' example).
  • Centering both ways: place one piece of content exactly in the middle of its parent's height, with no position math.
  • Input + button, sidebar + content: one side keeps a fixed size and the other takes all the remaining space (flex: 0 0 120px and flex: 1 1 0).
  • A footer pinned to the bottom: in a column, give the content flex-grow and the footer stays at the bottom edge even when the content is short.
  • Tag and chip lists: turn wrapping on and let items flow at their natural length. If every row needs the same column widths, as with cards, consider Grid. That is why, in the 'Growing cards' example, the cards on the last line get wider: each line shares out its own space.

How to use it

  1. Pick a starting point. Click one of the 12 example layouts and the container settings, item settings and container size all change at once. On a wide screen the stage stays pinned at the top while you scroll, so you can click through examples and compare the results right away.
  2. Set up the container. Choose the direction and wrapping first, then change the main-axis and cross-axis alignment. The alignment icons turn to match the current direction, so the way the bars in an icon move is the way the items really move.
  3. Drag the size. Narrow the container with the handle at the lower right of the stage to find the point where wrapping and shrinking begin. With the handle focused, the arrow keys change the size by 10px, Shift plus an arrow by 50px, and the Home key fits the width to the stage.
  4. Fine-tune an item. Select an item on the stage or with the numbered buttons, then change its text, flex values, order, align-self and auto margin. The size breakdown card shows how much of the free space that item received.
  5. Copy. Use 'Copy CSS' and 'Copy HTML' to take the code. The default code contains only the layout properties that differ from their defaults. Turn on 'Include preview styling' to add the same sizes, padding and borders as the stage, so the layout looks the same where you paste it.

Main axis and cross axis

The main axis is the direction in which items are laid out, and the cross axis is perpendicular to it. justify-content moves items along the main axis, and align-items, align-self and align-content move them along the cross axis. In a left-to-right horizontal writing mode, the four directions work like this.

flex-directionMain axisCross axisMain-axis startCross-axis start
rowHorizontalVerticalLeftTop
row-reverseHorizontalVerticalRightTop
columnVerticalHorizontalTopLeft
column-reverseVerticalHorizontalBottomLeft

flex-wrap: wrap-reverse swaps the start and end of the cross axis. So with row and wrap-reverse, lines stack from bottom to top, and align-items: flex-start also sticks to the bottom of each line. In right-to-left documents (direction: rtl) and in vertical writing modes the start side changes again, so it is easy to go wrong if you always read flex-start as 'left'.

justify-content shares out the free space

justify-content decides where the space left on the main axis goes, after the sizes of the items and the gaps have been taken out. If there is no free space, changing the value moves nothing. The table below shows the result for three 80px items with no gap in an inner width of 400px, which leaves 160px of free space.

ValueSpace beforeBetween itemsSpace afterLeft edge of the three items
flex-start001600 · 80 · 160
center8008080 · 160 · 240
flex-end16000160 · 240 · 320
space-between08000 · 160 · 320
space-around26.6753.3326.6726.67 · 160 · 293.33
space-evenly40404040 · 160 · 280

space-around gives each item the same space on both sides, so the space between items (53.33px) is twice the space at the ends (26.67px). space-evenly makes the ends and the spaces between items all equal. These three distribution values switch to a fallback alignment when the space cannot be divided. CSS Box Alignment defines the fallback for space-between as safe flex-start, and for space-around and space-evenly as safe center. So with a single item, space-between puts it at the start and the other two put it in the center. When the items overflow, safe protects the start side, so all three stick to the start (confirmed in Chromium 151).

align-items, align-self and align-content

align-items decides where each item sits on the cross axis within its line, and align-self overrides that value for one item. The default, stretch, stretches an item whose cross size is auto to the size of the line. In a horizontal layout, an item with an explicit height does not stretch. baseline lines up the first-line text baselines of items with different text sizes (see the 'Aligned text baselines' example).

align-content treats multiple lines as one block and places the whole block on the cross axis. The default, normal, behaves like stretch in a flex container: it stretches the lines to fill the free space. The spec says this property has no effect on a single-line flex container, so with flex-wrap: nowrap no value changes anything. With wrap it applies even if there happens to be only one line. In Chromium 151, with one 20px-high line of items in a 100px-high container and align-content: center, the line stayed at the top with nowrap, and with wrap it moved down 40px into the center.

The flex shorthand: initial, auto, none and 1

flex sets flex-grow, flex-shrink and flex-basis in one go. The spec presents four common values, listed below, and a single number such as flex: 1 sets flex-basis to 0. The two right-hand columns show two items with content widths of 100px and 300px placed in containers with an inner width of 600px and 300px.

ValueExpandedMeaningInner 600pxInner 300px
initial0 1 autoKeeps its content size and shrinks if space runs short (the default)100 · 300 (200 left)75 · 225
auto1 1 autoStarts from the content size and adds the free space equally200 · 40075 · 225
none0 0 autoKeeps its content size and neither grows nor shrinks100 · 300 (200 left)100 · 300 (100 over)
11 1 0Starts from 0 and shares all the space equally300 · 300150 · 150

The difference between flex: auto and flex: 1 is the starting point. auto starts from the content sizes (100 and 300) and adds half of the free 200 to each, so the longer item stays wider. 1 starts from 0 and splits the 600 in half, so both items end up the same width. The table was calculated for items with no padding or border and a minimum content width small enough not to matter. If a long word makes the minimum width larger than the share an item is given, that item stops at its minimum width and the remaining items share the leftover space again.

flex-grow is a ratio for sharing the free space

flex-grow is not a ratio of final sizes but a ratio for sharing out the free space. Below are the results for two items in an inner width of 500px.

Base sizegrowFree spaceFinal sizeLeft for alignment
100 · 1001 · 2300200 · 3000
100 · 1000.25 · 0.25300175 · 175150
100 · 1001 · 0300400 · 1000
0 · 01 · 2500166.67 · 333.330

With grow 1 : 2, the free 300px is simply split into 100 and 200, so the final widths are 200 : 300. For the final widths to be exactly 1 : 2, set the base size to 0, as in the last row (flex: 1 and flex: 2), and make sure the items have no padding or border and no minimum content width gets in the way. Items with 30px of padding and border, like those on this tool's stage, start from that 30px, so even flex: 1 and flex: 2 do not end up at exactly 1 : 2. When the grow factors of the growing items add up to less than 1, the spec shares out only that fraction of the free space. 0.25 + 0.25 = 0.5, so only half of the 300px, 150px, is shared, and the remaining 150px is placed by justify-content.

flex-shrink shrinks in proportion to the base size

When space runs short, the amount each item gives up is shared out in the ratio of its shrink value multiplied by its inner base size. The inner base size is the base size minus padding and border. That is why larger items shrink more, and why the same shrink value does not mean the same shrinkage. Below, 100px is missing from an inner width of 300px.

Base sizeshrinkPadding + borderFinal size
200 · 2001 · 10150 · 150
100 · 3001 · 1075 · 225
200 · 2001 · 30175 · 125
100 · 3001 · 140 on each item81.25 · 218.75

The last row is box-sizing: border-box with left and right padding and border totaling 40px. Because the shrink ratio is set by the inner base sizes, 60 : 260, the result differs from the no-padding case (75 · 225). The size breakdown card in this tool writes this calculation out as, for example, '(1 × 60) / 320 of the missing 100'. The same rule as for grow applies when the shrink factors add up to less than 1. In a 300px inner width, two 200px items with shrink 0.2 each add up to 0.4, so only 40% of the missing 100px, 40px, is removed: they become 180 · 180 and the remaining 60px overflows.

Items that won't shrink: min-width: auto

Even with flex-shrink at 1, an item does not get smaller than its minimum content width. For a flex item that is not a scroll container, the default min-width of auto (min-height in a column) is computed as the 'content-based minimum size' (spec §4.5). That is why a long address with nowhere to break, text set to white-space: nowrap, or an image with a large intrinsic size pushes out through the container. In the 'Long address that won't shrink' example, the red hatching at the right of the stage is the overflow length.

  • Give that item min-width: 0 and it can shrink below its content. The text will not wrap by itself, though, so handle the overflowing text separately with overflow-wrap: anywhere or an ellipsis.
  • Setting overflow to hidden or auto, anything but visible, turns the item into a scroll container, and its automatic minimum size becomes 0.
  • If a scrolling list inside a column keeps growing instead of scrolling, that item often needs min-height: 0.
  • In English and other languages that break lines only at spaces and hyphens, a long word or URL sets the minimum width. In the example, the 'Address' label stays on one line for that reason. For long strings, use overflow-wrap: anywhere, or set the lang attribute and use hyphens: auto so words can break.

Pushing one item away with an auto margin

In a horizontal layout, give an item margin-left: auto and that margin takes all the free space, pushing the item toward the end. The spec says positive free space goes to auto margins first, before justify-content and align-self do any aligning (§8.1). So on a line with an auto margin, changing justify-content moves nothing. The 'Navigation bar' example gives only the 'Log in' item an auto margin at its start, so the other menu items stay on the left and only 'Log in' sits at the right end. Put auto on both sides and the item sits in the middle of the free space. The tool's 'Main-axis auto margin' writes the right one of margin-left, right, top and bottom into the code to match the direction.

When gap and free space appear together

A flex container works out space in this order. First the gaps between items are subtracted from the inner size, then the remainder is shared out by grow or shrink. If space is still left, auto margins place it, and then justify-content. The first line of the size breakdown, 'inner size − gaps − sum of bases = free space', is exactly this order. In row, column-gap goes between items on the same line and row-gap between lines; in column it is the other way round.

gap appears only between items, never between the container's border and the first item. Give the edges space with the parent's padding. Used together with space-between, the visible spacing becomes wider than the gap, and a line with only one item has no gap.

order and reverse change only the visual order

order puts items with lower values first, and items with equal values keep their HTML order. row-reverse and column-reverse also flip the order only on screen. Keyboard Tab navigation and screen readers follow the HTML order, so the spec says to use order only to change the visual order, not the logical one (§5.4), and not to use order or *-reverse in place of a correct source order (§5). On this tool's stage too, the arrow keys move between items in HTML (numbered) order, not by screen position.

Browser support

FeatureChromeFirefoxSafari
flex, flex-basis (unprefixed)29229
order29209
gap in flex layout846314.1
flex-basis: content946115.4
flex-basis: min-content, max-content946616

The numbers in the table are the first supported versions listed in the MDN browser compatibility data. If you must support older browsers that lack gap in flex layout, use the items' margin to create the spacing instead.

Common mistakes

  • Vertical centering doesn't work. The parent is only as tall as its content, so there is no free space on the cross axis. Give the parent a height or min-height.
  • justify-content does nothing in a column. The main axis of a column is the height, so the parent needs a set height for there to be free space.
  • You set flex: 1 but the widths differ. Some item has a minimum content width, from a long word or an image, that is larger than the share it is given. Consider min-width: 0 on that item.
  • Only the cards on the last line get wider. Each line shares out its free space separately. To keep column widths equal, use Grid or set grow to 0.
  • Trying to align grandchildren. display: flex turns only direct children into flex items. To align the elements inside, give their parent display: flex as well.
  • With center, the start of the overflow is cut off. When items overflow, center spills equally on both sides, and the start side can't be reached even by scrolling. In Chromium 151, with 300px of content in a 200px container, the first item stuck out 50px to the front, and switching to justify-content: safe center put it at the start.
  • You changed the order but Tab order stays the same. That is normal. If the reading order must change as well, fix the HTML order.

Limits and notes

  • The stage shows only the left-to-right horizontal writing mode. In rtl or vertical documents the start side differs.
  • An item can hold only a single piece of text. In real pages with images, fixed-width children or nested flex, the minimum width comes out differently.
  • The size breakdown recalculates spec §9.7 using the content sizes (max-content and min-content) measured in the current browser. If a line is off by more than 1px, it shows the browser's value for that line and says so.
  • When flex-basis is smaller than padding + border (for example 0 with border-box), the spec's note describes the outer base size as 0. Chromium 151 starts the calculation from padding + border, and this tool uses the values that match that result.
  • Maximum sizes (max-width, max-height) and cross-axis auto margins on align-self are not adjustable.
  • The copied code does not generate media queries. Rules that change direction by screen width have to be written separately.
  • Copying a link stores the item text in the address as well. Don't enter text you don't want others to see.

As of The W3C CSS Flexible Box Layout Module Level 1 (Candidate Recommendation Draft 2025-10-14), the CSS Box Alignment Module Level 3 (Working Draft 2026-10-08) and the MDN browser compatibility data were checked against the originals on 2026-10-21. The table numbers come from this tool's calculation core, and the fallback alignment, align-content and base-size floor results were measured in Chromium 151.

Sources

  • 01W3C: CSS Flexible Box Layout Module Level 1Candidate Recommendation Draft 2025-10-14. §4.5 automatic minimum size, §5 and §5.4 order and accessibility, §7.1.1 flex keyword values (initial, auto, none, a number), §8.1 auto margins, §8.4 align-content, §9.3 collecting lines, §9.7 resolving flexible lengths (shrink × inner base size, grow factors sum < 1)
  • 02W3C: CSS Box Alignment Module Level 3Working Draft 2026-10-08. §4.3 distributed values and fallback alignment (space-between = safe flex-start, space-around and space-evenly = safe center), §4.4 safe and unsafe, §5.1.3 how normal behaves in flex containers
  • 03MDN: Basic concepts of flexboxMain and cross axes, start and end lines, the default behavior of flex items
  • 04MDN: flexBrowser compatibility table: unprefixed in Chrome 29, Firefox 22, Safari 9
  • 05MDN: flex-basisBrowser compatibility table: content in Chrome 94, Firefox 61, Safari 15.4; min-content and max-content in Chrome 94, Firefox 66, Safari 16
  • 06MDN: gapBrowser compatibility table: in flex layout, Chrome 84, Firefox 63, Safari 14.1
  • 07MDN: orderAccessibility caution that visual order and reading order diverge; browser compatibility table: Chrome 29, Firefox 20, Safari 9

Frequently asked questions

How do I center something horizontally and vertically with Flexbox?

Give the parent display: flex, justify-content: center and align-items: center. To center vertically, the parent must be taller than its content so there is free space on the cross axis, so also check height or min-height. Click 'Centered both ways' in the examples to see it at once.

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

justify-content shares out the free space along the main axis, the direction items are laid out in, while align-items sets each item's position on the cross axis, perpendicular to it. In row they are horizontal and vertical, in column vertical and horizontal. The alignment icons in this tool turn with the direction to show which way things move.

What is the difference between flex: 1 and flex: auto?

flex: 1 is 1 1 0, so it starts from 0 and shares all the space equally, while flex: auto is 1 1 auto, so it starts from the content size and adds only the free space equally. With items whose content is 100px and 300px in an inner width of 600px, flex: 1 gives 300 and 300, and flex: auto gives 200 and 400.

Does flex-grow: 2 mean twice as wide?

No. grow is a ratio for sharing out the free space. Two items with a base size of 100px in an inner width of 500px, with grow 1 and 2, split the free 300px into 100 and 200, so the final widths are 200 and 300. For exactly twice the width, set the base size to 0 and keep padding and border at 0.

Why does long text keep overflowing even though flex-shrink is 1?

The default min-width of auto on a flex item is computed from the minimum content width, so the item never gets smaller than that. Give the item min-width: 0, or set overflow to anything but visible, and it can shrink; handle the overflowing text separately, for example with overflow-wrap: anywhere.

I change align-content but nothing happens.

With flex-wrap: nowrap the container is single-line, so align-content has no effect. With wrap or wrap-reverse it applies even if there is only one actual line, and you need free space on the cross axis to see anything move.

Should I use Flexbox or Grid?

Use Flexbox when items sit in one direction and share space within that line, as in menus and button groups, and Grid when the edges of rows and columns must line up. Flexbox shares out space separately on each line even when it wraps, so the cards on the last line can end up wider.

Does changing order also change the Tab order?

No. order and row-reverse or column-reverse change only the order drawn on screen, while keyboard navigation and screen reading follow the HTML order. The spec says to use order only for visual order, so if the reading order matters, fix the HTML order.