CSS Tutorial / Flexbox Alignment, Wrapping, gap, grow, and shrink
Flexbox combines alignment, wrapping, and flexible sizing to fit items into available space. justify-content works along the main axis, align-items works across it, and align-content distributes multiple lines when there is cross-axis space to distribute.
Match alignment properties to their axes
| Property | Applicable to | Conditions to check |
|---|---|---|
| justify-content | Distribution of items along the main axis of the container | Space remaining after setting the item size |
| align-items | Cross-axis alignment of each item | Item cross axis size and line height |
| align-self | Cross-axis alignment of specific items | Change container default alignment individually |
| align-content | Alignment of the group of lines | Containers that can wrap and remaining space on the cross axis |
| gap | Spacing between adjacent items/lines | Space and division added by alignment |
In a row, justify-content mainly controls the horizontal, and align-items mainly controls the vertical. If you change it to column, the main axis becomes vertical and the physical direction of the two properties also changes. In particular, there must be space left in the container height to compare the justify-content of columns. If the height fits the content perfectly, there is almost no space to move even if you change the center or space-between. The direction of the axis and the start setting of the Flex container can be checked in Flexbox Basics: Containers, Items, and Axes cross axis.
justify-content: center places a group of items in the center, and space-between places the first and last items at both ends and divides the space between them. gap is the specified gap, and space-between distributes the remaining space. When used together, the actual gap may be larger than the gap. If an item's flex-grow uses up all the remaining space or the auto margin in the main axis direction takes up space, the change in justify-content may not be visible.
align-items: center aligns items of different heights to the center within one line. align-content: center centers all lines on the cross axis. You should not think of the two as the same function. align-content has no effect on single-line containers that are nowrap, and even in wrap containers, if the size occupied by the lines and the height of the container are the same, there is no room for comparison. You can check the application conditions in MDN's Flexbox alignment guide.
Compare item alignment and line alignment
Save the code below as flex-align.html and open it. The first section is three items of different heights, the second section is four items in two rows. In the second section, I set the height to 280px to make room for moving the bundle.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>flex-align.html</title>
<style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.toolbar { display: flex; gap: 12px; justify-content: space-between; align-items: center;
width: 100%; max-width: 640px; min-height: 120px; border: 2px solid #789; padding: 12px; }
.toolbar > div { padding: 8px; background: #dceefa; }
.lines { display: flex; flex-wrap: wrap; gap: 12px; width: min(100%, 360px); height: 280px;
align-items: center; align-content: flex-start; border: 2px solid #789; padding: 12px; }
.lines > div { flex: 0 0 140px; padding: 8px; background: #e8f5de; }
.tall { min-height: 60px; }
</style>
</head>
<body>
<h1>Alignment on one line and multiple lines</h1>
<h2>Toolbar</h2><div class="toolbar"><div>Short item</div><div>Two-line item<br>Second line</div><div>Button position</div></div>
<h2>Line group</h2><div class="lines"><div>1</div><div class="tall">2<br>Second line</div><div>3</div><div class="tall">4<br>Second line</div></div>
</body>
</html>
- Change the .toolbar's justify-content to center to see if the three items come together in the center. We also compare flex-start and return it to space-between. Leave the item size and gap as is.
- Change align-items in .toolbar to flex-start to make sure it aligns at the top. If you change it to stretch, the items with auto cross axis size will increase. After comparison, it is restored to center.
- Change only the align-content of .lines to center. A bundle of two lines comes down while maintaining the item relationships of each line. If you switch back to flex-start and only change align-items to flex-start, the position of short items in each line will change.
- If you just change the flex-wrap in .lines to nowrap, everything will try to stay on one line, and this example has collapse turned off, causing it to overflow horizontally. In this state, you cannot align multiple lines with align-content. After confirmation, restore it to wrap.
Understand grow, shrink, and basis
flex: 1 1 192px is grow, shrink, and basis in that order. basis is the standard size from which to start spatial distribution of the main axis and is not a value that guarantees the final width. Grow is the enlargement ratio for the remaining space, and shrink is the shrinkage ratio when space is insufficient. Since there is an omitted value rule for single numbers or auto in shorthand, three values are specified and compared in the learning example.
| declaration | When there is space left | When you run out of space |
|---|---|---|
| flex: 0 1 192px | Maintain standard size | Participate in downsizing |
| flex: 1 1 192px | The remaining space is distributed | Participate in downsizing |
| flex: 0 0 192px | Maintain standard size | No reduction. If it is nowrap, it can overflow. |
For example, if a parent with a content width of 640px contains three items of base size 100px and two gaps (each 20px), the remaining space is 640 − 300 − 40 = 300px. If the grow ratio is 1:2:1, the added space will be 75px, 150px, and 75px, and the final width will be 175px, 250px, and 175px. This is a calculation of conditions that do not involve minimum content size or min/max constraints.
The amount of shrinkage is not evenly distributed based on the shrink number alone. Consider both the reduction ratio and the reference size. If we need to reduce 60px of two items with standard sizes of 200px and 100px and both shrinks of 1, then under simple conditions without constraints, we would reduce 40px and 20px. The results may vary if there are padding, borders, minimum content size, etc., so you should actually check the applied values. MDN's flex description explains shorthand and size conditions.
Distribute space and wrap cards
Save the following code as flex-size.html. The calculation area corresponds to the above calculation by creating a maximum width of 640px without any additional padding or border. The card list uses a width of 192px as the standard for line breaks, but fills the remaining space. If a list with list-style: none is outside of nav, it may not be recognized as a list in Safari's accessibility tree. In the example, ul specifies role="list" to specify the list role. Accessibility conditions when removing bullets and spacing are also described in CSS Paragraph and List Styling.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>flex-size.html</title>
<style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.calc { display: flex; gap: 20px; width: min(100%, 640px); background: #eef2f6; }
.calc > div { flex: 1 1 100px; min-width: 0; height: 80px; background: #dceefa; }
.calc > div:nth-child(2) { flex-grow: 2; }
.cards { display: flex; flex-wrap: wrap; gap: 16px; list-style: none; padding: 0; }
.cards > li { flex: 1 1 192px; min-width: 0; padding: 16px; background: #e8f5de; overflow-wrap: anywhere; }
</style>
</head>
<body>
<h1>Flex values and space distribution</h1><div class="calc"><div>grow 1</div><div>grow 2</div><div>grow 1</div></div>
<h2>Wrapping card</h2><ul class="cards" role="list"><li>First card</li><li>Second card</li><li>Third card</li><li>Fourth card</li></ul>
</body>
</html>
- Expand your browser so that the .calc is 640px wide and use Developer Tools to check the widths of the three items. It will be 175px·250px·175px. If you change only the second item's grow to 1, the three items will become 200px each. After comparison, restore to 2.
- Just change the grow in .cards > li to 0 to make sure the last row of cards doesn't fill the extra width. If you restore it to 1, the last line will also receive space.
- Narrow the screen to see if fewer cards fit in a row. wrap determines which lines to place, and each line distributes the remaining space separately. The card widths of the last row and the previous row do not necessarily match.
- To see a single line overflow instead of a line break, replace flex-wrap with nowrap and item with flex: 0 0 192px. After checking the two conditions, restore the original wrap and 1 1 192px.
Check automatic minimum size and long text
The automatic minimum width of Flex items may prevent areas containing long addresses or identifiers from being shortened. CSS Overflow, Long Text Wrapping, and Ellipsis allows items to be collapsed, and overflow-wrap: anywhere allows the string itself to be wrapped. Shrinking a box does not automatically truncate the text within it, so you need to distinguish between the two problems.
Save the code below as flex-long-text.html. I entered a long identifier without spaces, not an actual address. Even if the screen is narrowed, the text next to the guidance area is read divided into multiple lines. You can check the line wrapping rules in MDN's overflow-wrap description.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>flex-long-text.html</title>
<style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.notice { display: flex; gap: 12px; max-width: 600px; border: 2px solid #789; padding: 12px; }
.icon { flex: 0 0 48px; background: #ffe4b5; }
.text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; background: #dceefa; }
.text p { margin: 0; }
</style>
</head>
<body>
<h1>Long strings and minimum sizes</h1><div class="notice"><div class="icon">Notice</div><div class="text"><p>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</p></div></div>
</body>
</html>
- In .text, just change overflow-wrap to normal. Even if the item width is reduced, the string may overflow out of bounds. Restore to anywhere.
- To see the impact of min-width separately, remove min-width: 0 while keeping overflow-wrap: normal. After determining how the minimum size of long strings affects item placement, we restore both declarations to their original values.
If alignment is not possible, first check the parent's axis and remaining space. If the size does not decrease, check the item's minimum size and internal string. If you put overflow: hidden on the entire parent to hide the problem, you may lose content or focus indication. It is easier to judge the results if the layout size and content display are resolved separately.










