How to create equal spacing between four blocks using Flexbox?
I have the following HTML code:
<div class="modal__box-nominal-list">
<ul>
<li><a href="javascript:void(0);" class="active_nominal">10 000 ₽</a></li>
<li><a href="javascript:void(0);">30 000 ₽</a></li>
<li><a href="javascript:void(0);">100 000 ₽</a></li>
</ul>
<label class="input-container" for="free_nominal">
<input id="free_nominal" name="free_nominal" class="input" type="text" placeholder="Amount must be a multiple of 100 and greater than 900" value="" inputmode="numeric">
</label>
</div>
I’m using the following CSS for Flexbox:
.modal__box-nominal-list {
width:100%;
display: flex;
gap: 10px;
flex-direction: column;
}
ul {
display: flex;
justify-content: space-between;
gap: 10px;
flex-wrap: wrap;
}
li {
display:block;
width:calc(33% - 6px); //half of gap +1px, as it will wrap on small screens
margin-top:0;
}
Problem: The spacing between the blocks is uneven. Between the first blocks, I have 13px and 11px, and between the third block and the input - 10px. What is the error in my code?
Your code contains several common errors that lead to uneven spacing. The main issues are related to incorrect width calculations of elements and the conflict between justify-content: space-between and flex-wrap: wrap.
justify-content: space-between creates uneven spacing when elements wrap to a new line because it tries to distribute space between all elements in a row, including the edge elements, which results in different intervals.
To create equal spacing between four blocks, it’s better to use modern approaches with the gap property and proper width calculations.
Table of Contents
- Solution using gap
- Alternative methods
- Optimizing your code
- Complete corrected example
- Responsiveness tips
Solution using gap
The most modern and reliable method uses the gap property to create equal intervals:
.modal__box-nominal-list {
width: 100%;
display: flex;
flex-direction: column;
gap: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
}
li {
flex: 1 1 calc(50% - 10px); /* 2 elements per row accounting for gap */
min-width: calc(50% - 10px);
}
Why this works:
gap: 10pxcreates equal intervals between elementsflex: 1 1 calc(50% - 10px)automatically distributes space accounting for margins- No need for complex calculations with
justify-content
Alternative methods
Method with negative margins
.modal__box-nominal-list {
width: 100%;
display: flex;
flex-direction: column;
gap: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
margin: 0 -5px; /* negative margin to compensate */
padding: 0;
list-style: none;
}
li {
width: calc(50% - 10px); /* 50% - 10px (2 with 5px margin each) */
margin: 5px; /* equal margins on both sides */
}
This approach is mentioned in sources as a reliable way to create equal spacing source.
Optimizing your code
The main errors in your original code:
- Incorrect width calculation:
calc(33% - 6px)doesn’t account for the actual amount of gap - Conflict between
space-betweenandflex-wrap: These properties don’t work well together - Missing list style reset: Default
marginandpaddingdisrupt the layout
Correct calculation for 3 elements per row with gap:
li {
flex: 1 1 calc(33.333% - 6.666px); /* 100% / 3 - (2 * 10px) / 3 */
min-width: calc(33.333% - 6.666px);
}
Complete corrected example
<div class="modal__box-nominal-list">
<ul>
<li><a href="javascript:void(0);" class="active_nominal">10 000 ₽</a></li>
<li><a href="javascript:void(0);">30 000 ₽</a></li>
<li><a href="javascript:void(0);">100 000 ₽</a></li>
</ul>
<label class="input-container" for="free_nominal">
<input id="free_nominal" name="free_nominal" class="input" type="text" placeholder="Amount must be a multiple of 100 and greater than 900" value="" inputmode="numeric">
</label>
</div>
.modal__box-nominal-list {
width: 100%;
display: flex;
flex-direction: column;
gap: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
}
li {
flex: 1 1 calc(33.333% - 6.666px);
min-width: calc(33.333% - 6.666px);
}
li a {
display: block;
padding: 10px;
text-align: center;
background: #f5f5f5;
border-radius: 4px;
text-decoration: none;
color: #333;
}
.input-container {
margin-top: 0; /* remove additional gap margin */
}
Responsiveness tips
For better responsiveness, use media queries:
@media (max-width: 768px) {
li {
flex: 1 1 calc(50% - 10px);
min-width: calc(50% - 10px);
}
}
@media (max-width: 480px) {
li {
flex: 1 1 100%;
min-width: 100%;
}
}
Important: Modern browsers well support the
gapproperty, but for older browsers you may need to use negative margins or prefixed stylesheets.
Sources
- Gap — a bright future for spacing in Flexbox (like in Grid)
- Simple way to set spacing between flexbox elements
- Vertical distance between elements in Flexbox: solution
- Flexbox guide — CSS — Doka
Conclusion
- Main problem: The conflict between
justify-content: space-betweenandflex-wrap: wrapleads to uneven spacing - Best solution: Use the
gapproperty to create equal intervals - Correct calculation: Element width should account for the number of gaps between them
- Responsiveness: Use media queries to change the number of elements per row on different screens
- Compatibility:
gapis well supported in modern browsers, for older ones use negative margins
Your layout will work correctly if you abandon justify-content: space-between and use the modern approach with gap and automatic space distribution via the flex property.