/
The flex-grow, flex-shrink, and flex-basis properties are the heart of CSS Flexbox. These three properties work together to control exactly how flex items behave when there's extra space or not enough space in the container. Understanding these properties deeply will transform how you approach flexible layouts.
Before diving into individual properties, it's important to understand that flex-grow, flex-shrink, and flex-basis are typically used together through the flex shorthand. The syntax is: flex: [grow] [shrink] [basis]. However, understanding each property individually is crucial for mastering flexible layouts.
/* The flex shorthand */
.item {
flex: 1 1 auto; /* grow shrink basis */
}
/* Is equivalent to: */
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
/* Common shorthand values */
.item-1 { flex: 1; } /* flex: 1 1 0% */
.item-2 { flex: auto; } /* flex: 1 1 auto */
.item-3 { flex: none; } /* flex: 0 0 auto */
.item-4 { flex: 0 auto; } /* flex: 0 1 auto (default) */flex-basis defines the initial main size of a flex item before any growing or shrinking occurs. Think of it as the 'ideal' size of the item. It can be set to a length (px, em, rem, %), the keyword 'auto', or 'content'. When set to auto, the browser uses the item's width or height (depending on flex-direction) as the basis.
/* flex-basis examples */
.container {
display: flex;
width: 600px;
}
/* Fixed basis */
.item-fixed {
flex-basis: 200px;
/* Item starts at 200px before grow/shrink */
}
/* Percentage basis */
.item-percent {
flex-basis: 25%;
/* Item starts at 25% of container (150px) */
}
/* Auto basis - uses content or width */
.item-auto {
flex-basis: auto;
width: 150px;
/* Item starts at 150px (from width) */
}
/* Content basis - sizes to content */
.item-content {
flex-basis: content;
/* Item starts at its natural content size */
}
/* Zero basis - commonly used with flex-grow */
.item-zero {
flex-basis: 0;
flex-grow: 1;
/* Item ignores content size, distributes all space evenly */
}While flex-basis and width might seem similar, they behave differently in a flex context. flex-basis only applies along the main axis and participates in the flex algorithm, while width is absolute. When both are set, flex-basis takes precedence for determining the initial size in flex calculations.
/* flex-basis takes precedence over width in flex context */
.item {
width: 300px;
flex-basis: 200px;
/* In flex container, item starts at 200px, not 300px */
}
/* However, min-width and max-width still apply */
.item-constrained {
flex-basis: 100px;
min-width: 150px;
max-width: 250px;
/* Item cannot shrink below 150px or grow above 250px */
}
/* Comparison in action */
.container {
display: flex;
width: 800px;
}
.item-a {
width: 200px; /* Ignored in flex calculation */
flex-basis: 100px; /* Used as starting point */
flex-grow: 1; /* Will grow from 100px */
}
.item-b {
flex-basis: 200px;
flex-grow: 1; /* Will grow from 200px */
}flex-grow determines how much of the available free space in the container should be assigned to the item. It accepts a unitless number as a proportion. A value of 0 means the item won't grow, while any positive number indicates it should grow relative to other items' flex-grow values.
/* Understanding flex-grow distribution */
.container {
display: flex;
width: 600px;
}
/* Scenario 1: Equal distribution */
.item {
flex-basis: 100px;
flex-grow: 1;
}
/*
3 items × 100px = 300px used
600px - 300px = 300px free space
Each item grows by 100px (300px ÷ 3)
Final size: 200px each
*/
/* Scenario 2: Proportional distribution */
.item-1 { flex-basis: 100px; flex-grow: 1; }
.item-2 { flex-basis: 100px; flex-grow: 2; }
.item-3 { flex-basis: 100px; flex-grow: 1; }
/*
Total grow: 1 + 2 + 1 = 4
Free space: 300px
item-1 grows: 300px × (1/4) = 75px → Final: 175px
item-2 grows: 300px × (2/4) = 150px → Final: 250px
item-3 grows: 300px × (1/4) = 75px → Final: 175px
*/Understanding the exact calculation helps you predict layouts precisely. The formula is: Final Size = flex-basis + (free space × (flex-grow / total flex-grow)). This calculation happens after flex-basis is applied but before min/max constraints.
/* Practical flex-grow patterns */
/* Pattern 1: One item takes remaining space */
.sidebar {
flex-grow: 0;
flex-basis: 250px;
}
.main-content {
flex-grow: 1;
flex-basis: 0;
/* Takes all remaining space after sidebar */
}
/* Pattern 2: Golden ratio distribution */
.small-section {
flex-grow: 1;
flex-basis: 0;
}
.large-section {
flex-grow: 1.618;
flex-basis: 0;
/* Approximately golden ratio proportion */
}
/* Pattern 3: Fixed + flexible items */
.logo {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 120px;
/* Fixed size, won't grow or shrink */
}
.nav {
flex-grow: 1;
flex-basis: 0;
/* Grows to fill available space */
}
.actions {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 200px;
/* Fixed size on the right */
}flex-shrink controls how items shrink when there isn't enough space in the container. Unlike flex-grow which distributes extra space, flex-shrink removes space proportionally when the container is too small. The default value is 1, meaning items will shrink equally by default.
/* Understanding flex-shrink */
.container {
display: flex;
width: 400px;
}
.item-1 { flex-basis: 200px; flex-shrink: 1; }
.item-2 { flex-basis: 200px; flex-shrink: 1; }
.item-3 { flex-basis: 200px; flex-shrink: 1; }
/*
Total basis: 600px
Container: 400px
Overflow: 200px to shrink
Each shrinks by: 200px ÷ 3 = 66.67px
Final sizes: ~133.33px each
*/
/* Preventing shrink on specific items */
.item-no-shrink {
flex-shrink: 0;
flex-basis: 200px;
/* This item will never shrink below 200px */
}
/* Proportional shrinking */
.item-a { flex-basis: 300px; flex-shrink: 1; }
.item-b { flex-basis: 300px; flex-shrink: 2; }
/*
In a 400px container (200px overflow):
item-a shrinks less, item-b shrinks more
*/flex-shrink calculations are more nuanced than flex-grow. The shrink amount considers both the flex-shrink factor AND the flex-basis. Items with larger flex-basis values contribute more to shrinking, even with equal flex-shrink values. The formula is: Shrink Amount = (flex-shrink × flex-basis / total shrink factors) × overflow.
/* flex-shrink weighted calculation example */
.container {
display: flex;
width: 500px;
}
.item-1 { flex-basis: 200px; flex-shrink: 1; }
.item-2 { flex-basis: 300px; flex-shrink: 1; }
/*
Total basis: 500px (no overflow, no shrinking needed)
*/
/* Now with overflow */
.container-small {
display: flex;
width: 400px;
}
.item-1 { flex-basis: 200px; flex-shrink: 1; }
.item-2 { flex-basis: 300px; flex-shrink: 1; }
/*
Overflow: 100px
Weighted shrink factors:
item-1: 1 × 200 = 200
item-2: 1 × 300 = 300
Total: 500
item-1 shrinks: 100 × (200/500) = 40px → Final: 160px
item-2 shrinks: 100 × (300/500) = 60px → Final: 240px
Notice: item-2 shrinks MORE because it has larger basis
*/Real-world layouts often combine these properties strategically. Here are battle-tested patterns that solve common layout challenges while maintaining flexibility across screen sizes.
/* Pattern: Responsive Card Grid */
.card-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
flex: 1 1 300px;
/*
flex-grow: 1 - cards grow to fill row
flex-shrink: 1 - cards can shrink if needed
flex-basis: 300px - ideal card width
Cards will be at least 300px, grow to fill space,
and wrap when they can't fit
*/
}
/* Pattern: Holy Grail Layout */
.holy-grail {
display: flex;
min-height: 100vh;
}
.sidebar-left {
flex: 0 0 200px;
/* Fixed width, never grows or shrinks */
}
.main {
flex: 1 1 auto;
/* Takes all available space, can shrink */
min-width: 0; /* Prevents content from forcing overflow */
}
.sidebar-right {
flex: 0 0 250px;
/* Fixed width, never grows or shrinks */
}
/* Pattern: Flexible Form Row */
.form-row {
display: flex;
gap: 1rem;
}
.form-label {
flex: 0 0 120px;
/* Fixed label width */
}
.form-input {
flex: 1 1 auto;
/* Input takes remaining space */
min-width: 200px;
/* But never smaller than 200px */
}/* Pitfall 1: Content overflow with flex-basis: 0 */
.item-problem {
flex: 1 1 0;
/* Long words or images can overflow! */
}
.item-solution {
flex: 1 1 0;
min-width: 0; /* Allow shrinking below content size */
overflow: hidden; /* Or handle overflow */
word-wrap: break-word;
}
/* Pitfall 2: Images not respecting flex-shrink */
.image-container {
flex: 1 1 200px;
}
.image-container img {
max-width: 100%; /* Image respects container size */
height: auto;
}
/* Pitfall 3: Uneven distribution with auto basis */
.item-auto {
flex: 1 1 auto;
/* Items with more content get more space! */
}
.item-even {
flex: 1 1 0;
/* Use 0 basis for truly even distribution */
}
/* Pitfall 4: Forgetting min-width defaults */
.flex-item {
flex: 1 1 0;
/* min-width defaults to 'auto' which can prevent shrinking */
min-width: 0; /* Reset to allow proper shrinking */
}Modern browser DevTools provide excellent flexbox debugging. In Chrome and Firefox, you can see flex-basis, flex-grow calculations, and final sizes visually. Look for the flexbox badge in the Elements panel and enable the flexbox overlay to see how space is distributed.
/* Debug helper class */
.flex-debug * {
outline: 1px solid red;
}
.flex-debug::before {
content: 'Container: ' attr(style);
display: block;
background: yellow;
font-size: 12px;
}
/* Temporary debug styles */
.item {
background: rgba(0, 100, 200, 0.2);
outline: 1px dashed blue;
/* Helps visualize actual item sizes */
}The flex shorthand (flex: grow shrink basis) is the recommended way to set these properties. Start with common patterns like flex: 1 for equal distribution or flex: none for fixed items. Remember that flex-basis: 0 ignores content size while flex-basis: auto respects it. Use min-width: 0 to allow items to shrink below their content size. Test with different content amounts to ensure your layout remains flexible.