CSS Grid introduced a flexible unit called fr (fractional unit). 1fr represents one fraction of the available space in a grid container.
If you’ve worked with percentages or px for column widths, the fr unit feels similar but handles remaining space automatically – no manual calculations needed.
The grid items in the examples below are positioned using the grid areas property:
.grid-wrap {
max-width: 100%;
margin: 3em auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 50px 150px 50px;
grid-template-areas: "head head2 . side" "main main2 . side" "footer footer footer footer";
}
Each of the four columns occupies the same width (space) in the grid.
Examples of Using fr
Here’s a similar grid, but with different fr values. Notice how the column widths adjust:
.grid-wrap {
/* ... */
grid-template-columns: 1fr 1fr 40px 20%;
grid-template-rows: 100px 200px 100px;
/* ... */
}In the final example, the sidebar occupies
2fr of the space. Its width matches the combined width of the first and second columns.
.grid-wrap {
/* ... */
grid-template-columns: 1fr 1fr 40px 2fr;
grid-template-rows: 100px 200px 100px;
/* ... */
}fr vs Percentages
At first glance, fr and % seem interchangeable. Three columns of 33.33% look the same as 1fr 1fr 1fr – until you add a gap.
Percentages are calculated from the container’s total width. They don’t account for gaps. A 3-column grid with 33.33% 33.33% 33.33% and a 20px gap adds up to 100% of the width plus 40px of gaps, causing horizontal overflow:
/* Overflows - 99.99% + 40px of gaps > container width */
grid-template-columns: 33.33% 33.33% 33.33%;
gap: 20px;
/* Works - fr accounts for gaps automatically */
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;The fr unit avoids this because the browser subtracts gaps first, then divides the remaining space among the fr tracks. No overflow, no manual math.
This is the main reason to prefer fr over % in grid layouts. Percentages still have a role when you need a column to stay at an exact proportion regardless of gaps, but for most layouts fr is the safer choice.
Mixed Units
You can mix fr with other unit types in the same declaration – percentages, fixed px values, or auto. The browser allocates fixed and percentage tracks first, then distributes the remaining space among the fr tracks.
Here’s how the calculation works step by step on an 800px container with grid-template-columns: 300px 10% 1fr 2fr:
- Fixed tracks first: 300px is reserved.
- Percentage tracks: 10% of 800px = 80px.
- Remaining space: 800 – 300 – 80 = 420px.
- Distribute among fr tracks: 420px ÷ 3 total fr = 140px per fr. The
1frcolumn gets 140px, the2frcolumn gets 280px.
If there’s a gap, it’s subtracted in step 3 as well. With gap: 20px and 3 gaps between 4 columns, the remaining space would be 420 – 60 = 360px, giving 120px per fr.
main {
width: 800px;
display: grid;
grid-template-columns: 300px 10% 1fr 2fr;
/* Result: 300px 80px 140px 280px */
grid-template-rows: auto;
}fr vs auto
The auto keyword sizes a column to fit its content. The fr unit distributes remaining space regardless of content size.
When you combine them, auto columns shrink-wrap their content first, then fr columns split whatever is left:
grid-template-columns: auto 1fr auto;
/* sidebar | flexible main | sidebar */This is a common pattern for page layouts where sidebars should be as wide as their content, and the main area fills the rest. It also works nicely with the aspect-ratio property for grid cards that maintain proportions.
fr with repeat() and minmax()
The fr unit pairs well with responsive grid patterns that avoid media queries. Using repeat() with minmax() creates grids that automatically wrap items to the next row:
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));Each column is at least 250px wide. When there’s extra space, the 1fr maximum distributes it evenly across columns.
As the viewport shrinks, columns drop to a new row instead of getting squeezed below 250px. If you care about rendering speed, check my post on CSS Grid and web performance.
The difference between
auto-fillandauto-fit:auto-fillkeeps empty tracks when space is available, whileauto-fitcollapses them so existing items stretch to fill the row.
Common Pitfalls
A few things that trip up developers working with the fr unit for the first time:
1. fr doesn’t work outside Grid
Unlike % or px, the fr unit only applies to grid-template-columns and grid-template-rows. Using it in width, margin, or Flexbox properties has no effect.
2. Overflow with large content
An fr column can grow beyond its calculated fraction if its content doesn’t fit. To prevent this, use minmax(0, 1fr) instead of 1fr:
/* Default: fr uses content size as minimum */
grid-template-columns: 1fr 1fr;
/* Force minimum to 0 - content will overflow instead of expanding */
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);3. fr doesn’t work inside calc()
The fr unit is a <flex> data type, not a <length> like px or %. That means calc(1fr - 20px) is invalid and will be ignored. If you need a minimum size with flexible growth, use minmax() instead: minmax(200px, 1fr).
4. Gaps eat into fr space
The gap property is deducted before fr values are calculated. A 3-column 1fr 1fr 1fr grid with a 20px gap actually gives each column (total - 40px) / 3, not total / 3.
FAQs
1fr means one fraction of the available space in a grid container. If you have grid-template-columns: 1fr 1fr 1fr, the container's width (minus any gaps) is divided into three equal columns.fr unit distributes the remaining space after fixed sizes, percentages, and gaps are subtracted. This makes fr safer for grids with gaps because it won't cause overflow.fr unit only works inside grid-template-columns and grid-template-rows. It has no effect in Flexbox, width, margin, or any other CSS property.auto sizes a track to fit its content. fr distributes remaining space regardless of content. When used together, auto tracks are calculated first, then fr tracks split whatever space is left.fr track is auto, which means content can push the column wider than its fractional share. To fix this, use minmax(0, 1fr) instead of 1fr so the column can shrink below its content size.fr units are calculated. For example, a 900px container with gap: 30px and 1fr 1fr 1fr gives each column 280px, not 300px, because two 30px gaps total 60px.fr unit is a <flex> data type, not a <length>. Writing calc(1fr - 20px) is invalid CSS and will be ignored. If you need a flexible column with a minimum size, use minmax(20px, 1fr) instead.1fr is a fraction of the remaining space after fixed sizes, percentages, and gaps are subtracted. In a 900px container with one 300px column and two 1fr columns, each 1fr resolves to 300px. Change the container width or the fixed column and the pixel value changes with it.Summary
I use the fr unit in almost every grid I build. It removes the guesswork of calculating percentages and adapts naturally when you add or remove columns. Mixed with px, auto, and minmax(), it covers most layout needs without a single media query.
If you’re getting started with Grid, the complete guide covers the full picture – tracks, placement, alignment, and more.


Hmm… seems to me there might be an error(s) on the page as the examples don’t seem to be displaying correctly at all, whereas the original post you referenced/translated from (re; alligator, which actually redirects to digitalocean) displays perfectly/as intended.
Lots of confusion here. ¯\_(ツ)_/¯
Hey Matt!
I appreciate you notifying me about the errors. It’s been fixed!
All the best 🙂
Beauty!
Cheers, Roee