flex-grow & flex-shrink
flex-grow controls how much an item expands when there's extra space. flex-shrink controls how much an item compresses when space is tight. Both use proportional values: higher values get proportionally more/less space. Understanding these properties is key to responsive flex layouts.
flex-grow: distributing extra space
CSS
<!-- flex-grow: how item shares extra space -->
.container {
display: flex;
width: 600px; /* extra space available -->
gap: 0;
}
.item {
flex: 0 1 auto; /* flex-grow: 0 (doesn't grow) -->
width: 100px;
/* All items 100px, extra space left empty */
}
<!-- [100px] [100px] [100px] [extra 300px space] -->
/* All items grow equally -->
.container {
display: flex;
width: 600px;
gap: 0;
}
.item {
flex-grow: 1; /* each grows equally -->
flex-basis: 0; /* start from 0, grow to share space -->
}
<!-- [200px] [200px] [200px] equally distributed -->
/* Different growth rates -->
.container {
display: flex;
width: 600px;
gap: 0;
}
.item:nth-child(1) {
flex: 1 1 100px; /* grows 1 unit from 100px base -->
}
.item:nth-child(2) {
flex: 2 1 100px; /* grows 2 units from 100px base -->
}
.item:nth-child(3) {
flex: 1 1 100px; /* grows 1 unit from 100px base -->
}
<!-- Total: 1+2+1 = 4 units growth -->
<!-- Item 2 gets 2/4 (50%) of extra space -->
<!-- Items 1 & 3 each get 1/4 (25%) of extra space -->
/* One item grows, others fixed -->
.container {
display: flex;
width: 600px;
gap: 0;
}
.sidebar {
flex: 0 0 200px; /* fixed 200px -->
}
.content {
flex: 1; /* takes all extra space -->
}
<!-- [200px fixed] [remaining space] -->
/* Common ratios -->
.two-column {
flex: 2 1 0; /* takes 2/3 -->
}
.one-column {
flex: 1 1 0; /* takes 1/3 -->
}flex-shrink: handling space shortage
CSS
<!-- flex-shrink: how item compresses when cramped -->
.container {
display: flex;
width: 300px; /* not enough space -->
gap: 0;
}
.item {
flex-basis: 100px; /* wants 100px -->
flex-shrink: 0; /* won't shrink -->
}
<!-- [100px] [100px] [100px] overflow! -->
/* All items shrink equally -->
.container {
display: flex;
width: 300px; /* cramped -->
gap: 0;
}
.item {
flex-basis: 100px; /* wants 100px each -->
flex-shrink: 1; /* can shrink equally -->
}
<!-- [~75px] [~75px] [~75px] equally compressed -->
/* Different shrink rates -->
.container {
display: flex;
width: 300px; /* space shortage -->
gap: 0;
}
.important {
flex: 0 0 150px; /* won't shrink -->
}
.flexible {
flex: 1 1 150px; /* shrinks if needed -->
}
<!-- [150px fixed] [~150px shrinks] -->
/* One item protected from shrinking -->
.container {
display: flex;
gap: 10px;
}
.button {
flex: 0 0 auto; /* button size never shrinks -->
padding: 10px 20px;
white-space: nowrap;
}
.input {
flex: 1; /* input can shrink -->
min-width: 200px; /* but not below 200px -->
}Practical flex-grow and flex-shrink patterns
Pattern | flex Property | Behavior |
|---|---|---|
Fixed item | 0 0 200px | Never grows or shrinks |
Growing item | 1 1 0 | Takes all extra space |
Flexible item | 1 1 auto | Flexible both ways |
Protected item | 0 0 auto | Content-sized, no flex |
Two-to-one ratio | 2 1 0 and 1 1 0 | Different growth rates |
CSS
<!-- Responsive sidebar layout -->
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<main class="content">Content</main>
</div>
.layout {
display: flex;
gap: 20px;
width: 100%;
}
.sidebar {
flex: 0 1 300px; /* starts at 300px, can shrink but not grow -->
min-width: 250px; /* never smaller than 250px -->
}
.content {
flex: 1; /* takes remaining space -->
min-width: 400px; /* but needs at least 400px -->
}
<!-- Sidebar flexible, content flexible, content gets priority -->
/* Three-column with different ratios -->
.three-col {
display: flex;
gap: 20px;
width: 100%;
}
.col-left {
flex: 1 1 0; /* 1 unit -->
}
.col-middle {
flex: 2 1 0; /* 2 units (2x wider) -->
}
.col-right {
flex: 1 1 0; /* 1 unit -->
}
<!-- [25%] [50%] [25%] distribution -->
/* Toolbar with spacer -->
.toolbar {
display: flex;
gap: 10px;
padding: 10px;
border-bottom: 1px solid #ddd;
}
.tool-group {
display: flex;
gap: 5px;
flex: 0 0 auto; /* group doesn't grow -->
}
.spacer {
flex: 1; /* pushes following items right -->
}
.actions {
display: flex;
gap: 5px;
flex: 0 0 auto; /* actions don't grow -->
}
<!-- [tools] [spacer] [actions] -->
/* Input field with button -->
.input-group {
display: flex;
gap: 10px;
width: 100%;
}
input {
flex: 1; /* grows to fill space -->
min-width: 200px;
}
button {
flex: 0 0 auto; /* button never shrinks -->
padding: 10px 20px;
white-space: nowrap;
}
<!-- [input grows] [button fixed] -->flex-grow and flex-shrink ratio calculation
CSS
<!-- How grow factors work -->
.container {
display: flex;
width: 900px; /* 600px of space after 300px items -->
gap: 0;
}
.item-a {
flex: 1 1 100px; /* base 100px, grow 1 -->
}
.item-b {
flex: 2 1 100px; /* base 100px, grow 2 -->
}
.item-c {
flex: 1 1 100px; /* base 100px, grow 1 -->
}
/* Total growth needed: 900-300 = 600px -->
/* Growth units: 1+2+1 = 4 total -->
/* Item A: 100 + (600 * 1/4) = 100 + 150 = 250px -->
/* Item B: 100 + (600 * 2/4) = 100 + 300 = 400px -->
/* Item C: 100 + (600 * 1/4) = 100 + 150 = 250px -->
<!-- How shrink factors work -->
.container {
display: flex;
width: 300px; /* shortage of 300-300 = 0, or 100 items shortage -->
gap: 0;
}
.item-protected {
flex: 1 0 100px; /* no shrink -->
}
.item-flexible {
flex: 1 1 100px; /* can shrink -->
}
/* Item protected stays 100px -->
/* Item flexible shrinks to fill remaining space -->
<!-- [100px] [200px after shrink] -->
/* Comparing grow vs shrink behavior -->
.container {
display: flex;
width: 300px;
}
.item {
flex: 1 2 100px;
/* flex-grow: 1 (grows 1 unit if space available) -->
/* flex-shrink: 2 (shrinks 2 units if cramped - faster shrink) -->
}
<!-- Item shrinks faster than it grows (asymmetric) -->Note
`flex-grow` distributes extra space proportionally. `flex-shrink` compresses items proportionally when space is tight. Use `flex: 1 1 0` for equal-width columns, `flex: 0 0 auto` for fixed items, and `flex: 1 1 auto` for flexible items that maintain content size.
Next
Flex sizing with basis: [flex-basis](/css/flex-basis).