CSS Grid: Even Columns with Space-Between Gaps Flush Edges
Learn to evenly distribute columns in CSS Grid like Flexbox space-between using gap property and minmax(0,1fr). Perfect for calculator layouts with buttons flush to container edges, no outer padding.
How to evenly distribute columns in CSS Grid with equal gaps between them, similar to justify-content: space-between in Flexbox, ensuring buttons align flush to container edges?
I’m building a calculator layout using CSS Grid for buttons arranged in 4 columns. I want even spacing between columns (like Flexbox space-between), with the leftmost and rightmost buttons flush against the container’s left and right edges—no extra space on the sides.
Current HTML Structure
<div class="calculator">
<div class="screen">Screen</div>
<div class="button-container">
<button>AC</button>
<button>()</button>
<button>%</button>
<button>+</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>*</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>-</button>
</div>
</div>
Current CSS
.calculator {
border-radius: 1.5rem;
min-height: 80vh;
max-width: 350px;
background-color: #fae4e4;
padding: 1rem;
margin: 0 auto;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.screen {
min-height: 100px;
border-radius: 1rem 1rem 0 0;
background-color: #ded3d3;
padding: 1rem;
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 2rem;
}
.button-container {
padding-top: 0.5rem;
display: grid;
grid-template-columns: repeat(4, 1fr);
justify-content: space-between;
row-gap: 1rem;
text-align: center;
}
.button-container button {
border-radius: 50%;
height: 3rem;
width: 3rem;
background-color: #ffcccc;
border: none;
font-size: 1.5rem;
cursor: pointer;
transition: background-color 0.3s;
}
.button-container button:hover {
background-color: #ffb3b3;
}
Problem
Using grid-template-columns: repeat(4, 1fr) creates equal-width columns, but justify-content: space-between doesn’t distribute space evenly between columns as in Flexbox. I need consistent gaps between columns and no padding/margin on the outer edges.
What I’ve Tried
justify-content: space-betweenon.button-container: No effect on grid column spacing.- Adjusting
gap: Adds space between but doesn’t ensure flush edges or even distribution likespace-between.
Desired Outcome
- Equal gaps only between the 4 columns.
- First column button touches left edge of
.button-container. - Last column button touches right edge.
- Works responsively within the calculator container.
Use CSS Grid’s gap (column-gap) and proper track sizing — not justify-content — to get equal space between columns while keeping the outer columns flush. Change your grid to grid-template-columns: repeat(4, minmax(0, 1fr)), use gap (or column-gap) for the spacing, remove any horizontal padding on the grid container, and either make buttons fill their column or snap the first/last column items to start/end with justify-self (nth-child).
Contents
- How CSS Grid handles spacing — gap vs justify-content
- Minimal CSS fix — gap & grid-template-columns (copy/paste)
- Two practical approaches: fill columns vs fixed circular buttons
- Option A — Buttons fill each column (simplest flush edges)
- Option B — Fixed-size circular buttons, edges flush with nth-child
- Responsive tweaks and accessibility
- Debug checklist
- Sources
- Conclusion
How CSS Grid handles spacing — gap vs justify-content
Why doesn’t justify-content: space-between do what it does in Flexbox? In Grid, justify-content aligns the entire grid block inside the container; it doesn’t distribute space between columns. The property that creates equal space between grid tracks is gap (or its longhands column-gap / row-gap) — it adds space only between items, not at the outer edges, which is exactly what you want. See the MDN note on the relationship of Grid layout and the gap behaviour for confirmation: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Relationship_of_grid_layout and the column-gap reference: https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap.
In short: use gap for equal inter-column spacing and make sure your grid tracks are sized so the grid spans the container (so the first/last tracks sit flush).
I’ll show two practical ways to achieve your calculator layout below.
Minimal CSS fix — gap & grid-template-columns (copy/paste)
Replace the .button-container block and add two small rules. This keeps your circular buttons (3rem) and makes the leftmost/rightmost buttons touch the grid edges while keeping equal gaps between columns.
.button-container {
/* keep the top spacing, but remove horizontal padding so grid edges = container edges */
padding-top: 0.5rem;
padding-left: 0;
padding-right: 0;
display: grid;
/* allow tracks to shrink below min-content and share remaining space equally */
grid-template-columns: repeat(4, minmax(0, 1fr));
/* equal spacing only between columns/rows */
gap: 1rem; /* shorthand sets both column-gap and row-gap */
row-gap: 1rem;
/* center items by default (so middle column buttons look centered) */
justify-items: center;
align-items: center;
}
/* snap items that live in column 1 to the left edge of their track,
and items in column 4 to the right edge of their track */
.button-container > *:nth-child(4n+1) { justify-self: start; } /* col 1, 5, 9... */
.button-container > *:nth-child(4n) { justify-self: end; } /* col 4, 8, 12... */
/* keep your button look */
.button-container button {
width: 3rem;
height: 3rem;
border-radius: 50%;
background-color: #ffcccc;
border: none;
font-size: 1.5rem;
cursor: pointer;
transition: background-color 0.3s;
}
Why this works:
gaponly creates room between columns — the first and last grid tracks remain flush to the container edges.minmax(0, 1fr)prevents the columns from being widened by intrinsic content, so the grid actually divides the available width evenly.- The
nth-childrules place first/last column buttons at the track edges while leaving other buttons centered.
If you want every button to reach the edges of its track (no centering hacks), see Option A below.
Two practical approaches: fill columns vs fixed circular buttons
Option A — Buttons fill each column (simplest flush edges)
Make each button fill its column. This guarantees the button (or its visible box) touches the container edges without special selectors.
.button-container {
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1rem;
justify-items: stretch;
align-items: stretch;
padding-left: 0;
padding-right: 0;
}
.button-container button {
width: 100%;
aspect-ratio: 1 / 1; /* keep square buttons */
max-width: 4rem; /* optional cap on very wide screens */
border-radius: 0.5rem; /* or 50% if you prefer circles */
}
Pros:
- Zero hacks; first and last columns are flush automatically.
- Responsive: columns scale, buttons keep square shape via
aspect-ratio.
Cons:
- Buttons size = available column width; you may need
max-widthso they don’t become huge on wide screens.
Relevant reference on gap: https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap and the CSS-Tricks Grid guide: https://css-tricks.com/snippets/css/complete-guide-grid/
Option B — Fixed-size circular buttons, edges flush using nth-child (keeps 3rem circles)
This is the copy/paste solution in the Minimal CSS fix. It preserves 3rem circular buttons, centers interior column buttons, and forces the outer column items to hug the edges:
- Use
grid-template-columns: repeat(4, minmax(0, 1fr)) - Use
gap: 1rem - Set
justify-items: center - Then target items in the first and fourth column with nth-child selectors to
start/end
This keeps the aesthetic of small circular buttons while meeting your flush-edge requirement.
Reference example and community discussion of similar tactics: https://stackoverflow.com/questions/46951008/equal-space-between-grid-items-with-first-and-last-pinned-to-container-edges and https://stackoverflow.com/questions/70770416/how-do-make-columns-in-a-grid-space-evenly-like-with-flexbox
Responsive tweaks and accessibility
- Prevent overly-small columns by using a minimum:
grid-template-columns: repeat(4, minmax(44px, 1fr));— that ensures each button has a usable minimum on small screens. - Or use
repeat(auto-fit, minmax(44px, 1fr))if you want fewer columns on tiny screens. - Keep
box-sizing: border-box;globally to avoid unexpected width calculations. - For keyboard users, add a visible focus style:
.button-container button:focus {
outline: 2px solid #333;
outline-offset: 2px;
}
- If you need the buttons to be visually flush with the outer edge of the whole
.calculator(not just.button-container), remove horizontal padding from.calculatoror move padding to.screenso the grid can span full width. Avoid negative margins — restructure instead.
For a calculator UI tutorial that uses grid and gap for neat layouts, see https://freshman.tech/css-grid-calculator/ and general grid examples at https://gridbyexample.com/examples/example33/.
Debug checklist
If things still look off, check this:
- Remove any horizontal padding on
.button-container(and/or verify.calculatordoesn’t add unwanted padding). - Confirm
gapis set (open Styles in DevTools and look atcolumn-gap/row-gap). - Verify
grid-template-columnsusesminmax(0, 1fr)rather than plain1frif content is wide. - Check for margins on the
buttonelements — margins create extra outer spacing. - Use browser DevTools’ Grid inspector to see tracks/gaps (Chrome/Firefox have grid overlays).
- If you used nth-child selectors, make sure your element count and column count match (nth-child(4n+1) and nth-child(4n) for 4 columns).
Sources
- MDN — column-gap
- MDN — Relationship of grid layout to other layout methods
- CSS-Tricks — Complete Guide to Grid
- Grid by Example — Aligning the grid with space-around and space-between
- W3Schools — CSS column-gap property
- Stack Overflow — make columns in a grid “space-evenly” like with flexbox
- Stack Overflow — equal space between grid items with first/last pinned
- Tailwind CSS — gap docs
- Freshman.tech — calculator layout with CSS Grid
Conclusion
CSS Grid gives you the exact behavior you want when you use the gap property and proper track sizing (minmax(0, 1fr)). Remove horizontal padding on the grid container, use gap for equal inter-column spacing, and choose one of two patterns: make buttons fill each column (simpler) or keep fixed-size buttons and snap first/last column items to edges with justify-self (nth-child). Try the minimal copy/paste fix above — it should give you evenly distributed columns, equal gaps, and outer buttons flush to the .button-container edges.