How can I create 4 blocks with equal spacing between them 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:
.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;
}
However, the spacing between the blocks is uneven. I have 13px and 11px between the first blocks, and 10px between the third block and the input field. What is the error in my code?
Creating 4 Blocks with Equal Spacing Using Flexbox
To create 4 blocks with equal spacing between them using Flexbox, you need to properly configure the styles and structure. The main problem in your code lies in the incorrect combination of properties and inaccurate calculation of element widths.
Table of Contents
- Common Errors in Your Code
- Correct Solution for 4 Blocks
- Alternative Approaches
- Solution for Responsive Design
- Common Problems and Their Solutions
Common Errors in Your Code
-
Incorrect Structure: You have 3 list items + 1 input field, but you’re trying to style only the list while ignoring the overall container.
-
Property Conflict: Using both
justify-content: space-betweenandgap: 10pxsimultaneously creates conflicting results in space distribution. -
Incorrect Width Calculation:
width: calc(33% - 6px)is designed for 3 elements, but you need 4 blocks. -
Double Margin: Both the container and list have
gap: 10px, which doubles the spacing.
As explained in the Flexbox Guide, the gap property is the preferred method for creating uniform spacing between elements.
Correct Solution for 4 Blocks
Here’s the corrected code for creating 4 blocks with equal spacing:
<div class="modal__box-nominal-list">
<a href="javascript:void(0);" class="nominal-item active_nominal">10 000 ₽</a>
<a href="javascript:void(0);" class="nominal-item">30 000 ₽</a>
<a href="javascript:void(0);" class="nominal-item">100 000 ₽</a>
<div class="input-container">
<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">
</div>
</div>
.modal__box-nominal-list {
width: 100%;
display: flex;
gap: 10px; /* Equal spacing between all elements */
flex-wrap: wrap; /* Wrap on small screens */
}
.nominal-item {
flex: 1 1 calc(25% - 10px); /* Equal width accounting for gaps */
min-width: calc(25% - 10px);
text-align: center;
padding: 10px;
/* Other styles for buttons */
}
.input-container {
flex: 1 1 calc(25% - 10px); /* Same width as other elements */
min-width: calc(25% - 10px);
}
.input {
width: 100%;
/* Styles for input field */
}
This approach uses the modern method with the gap property, as recommended by modern CSS standards. The calculation calc(25% - 10px) accounts for 25% width minus half the gap on each side.
Alternative Approaches
1. Using justify-content with Equal Margins
.modal__box-nominal-list {
width: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.nominal-item, .input-container {
width: calc(25% - 7.5px); /* 25% minus 3/4 of the gap */
}
2. Responsive Solution with flex-basis
.modal__box-nominal-list {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.nominal-item, .input-container {
flex: 0 0 calc(50% - 5px); /* 2 per row on large screens */
}
@media (min-width: 768px) {
.nominal-item, .input-container {
flex: 0 0 calc(25% - 7.5px); /* 1 per row on small screens */
}
}
As noted in the article on Flexbox, this approach ensures automatic space distribution between elements.
Solution for Responsive Design
For full responsiveness, you can use the following solution:
.modal__box-nominal-list {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: stretch;
}
.nominal-item, .input-container {
flex: 1 1 calc(50% - 5px); /* 2 per row on mobile */
min-width: calc(50% - 5px);
}
@media (min-width: 600px) {
.nominal-item, .input-container {
flex: 1 1 calc(33.333% - 6.66px); /* 3 per row on tablets */
min-width: calc(33.333% - 6.66px);
}
}
@media (min-width: 992px) {
.nominal-item, .input-container {
flex: 1 1 calc(25% - 7.5px); /* 4 per row on desktop */
min-width: calc(25% - 7.5px);
}
}
Common Problems and Their Solutions
Problem: Uneven spacing between elements
Cause: Conflict between gap and justify-content
Solution: Use only gap for equal spacing in modern browsers
Problem: Elements wrapping to new lines unevenly
Cause: Incorrect min-width calculation
Solution: Ensure min-width equals flex-basis
Problem: Input field has different height
Cause: Different content in elements
Solution: Add align-items: stretch to equalize height
As explained by Er Raj Aryan, the modern approach using the gap property solves most spacing issues in Flexbox and Grid layouts.
Sources
- CSS Flexbox Guide — design.dev
- CSS Flexbox: The Power of Flexible Box Layouts - DEV Community
- Basic CSS 02 — CSS Layouts (Flexbox, Positioning, Margin/Padding) - Medium
- Self Gap: Customizing Spacing Between Specific Flex or Grid Items in CSS - Medium
Conclusion
- Main problem in your code is conflicting properties and incorrect structure for 4 elements
- Correct approach uses the
gapproperty for equal spacing andflex: 1 1 calc(25% - 10px)for equal width distribution - Modern browsers fully support
gap, making it the preferred method for creating spacing - For responsive design, use media queries to change the number of items per row
- Avoid simultaneous use of
justify-contentandgapfor the same container, as this creates conflicting results
Apply the proposed solutions, and you’ll get 4 blocks with perfectly equal spacing between them on all devices.