Reputation: 4116
How can I control the middle space between 2 flex items in a row? My goal is to minimize the middle space between the items.
In other words, I want to right and center align the columns, while keeping the text centered.
I would also like to be able to control the middle gutter. Also, maybe be able to say that the middle gutter should be some fixed pixel quantity like 20px.
.row {
display: flex;
}
.column {
border: 1px solid #ccc;
width: 50%;
}
h2 {
text-align: center;
}
<div class="row">
<div class="column first">
<h2>Centered</h2>
<h2>Text</h2>
</div>
<div class="column second">
<h2>Centered</h2>
<h2>Text</h2>
</div>
</div>
.row {
display: flex;
}
.column {
border: 1px solid #ccc;
width: 50%;
}
h2 {
text-align: center;
}
.first h2 {
text-align: right;
}
.second h2 {
text-align: left;
}
<div class="row">
<div class="column first">
<h2>Centered</h2>
<h2>Text</h2>
</div>
<div class="column second">
<h2>Centered</h2>
<h2>Text</h2>
</div>
</div>
Upvotes: 2
Views: 4900
Reputation: 90078
If you want your elements to have a particular proportion in relation to each other or to the whole (i.e: 50%
), flexbox is not even the best solution (although it can be crow-bared to fulfill the requirement).
A simple display: inline-block; width: 50%; box-sizing: border-box
on the children will do.
Flexbox was designed to allow fluid distribution of positive or negative space.
As in, after the browser determines how much space the children need and how much they have available, by comparing the two it deals with two cases:
flex-grow
values (until the space is filled) or, if no children have positive flex-grow
values, distribute the space in between the childrenflex-shrink
values.You have a case of positive space, where the children do not have flex-grow
, so the space can be redistributed in between them. You have three options:
justify-content: space-between
justify-content: space-around
justify-content: space-evenly
Notice how the spaces are equally distributed in each case. That's why it's called flexbox
, that's what it was designed for and, if you want, that's its superpower.
When you set width: 50%
you kind of take all of that away:
.row {
display: flex;
width: 100%;
}
.row>* {
border: 1px solid #ccc;
text-align: center;
}
.one {
justify-content: space-between;
}
.two {
justify-content: space-around;
}
.three {
justify-content: space-evenly;
}
.grow>* {
flex-grow: 1;
margin: 1rem;
}
<code>justify-content: space-between</code>
<div class="row one">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-between (unequal)</code>
<div class="row one">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>justify-content: space-around;</code>
<div class="row two">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-around; (unequal)</code>
<div class="row two">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>justify-content: space-evenly;</code>
<div class="row three">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-evenly; (unequal)</code>
<div class="row three">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>> flex-grow: 1;</code>
<div class="row grow">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>> flex-grow: 1; (unequal elements)</code>
<div class="row grow">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
A more detailed explanation on how flexbox
works can be found here.
The official spec is here.
Considering your question, there's a big chance justify-content: space-evenly
does what you want, but I can't be sure, as your question is not extremely clear.
Important note: You can always use margin
and padding
on your elements, which will push them around accordingly. Also note margin: auto
on flexbox
children will steal the positive space from flexbox and will redistribute it equally between all the margin:auto
s present in parent space (and will make it look like flexbox doesn't work properly; it actually does, but there's nothing left to redistribute).
If you want to have a particular distance in between your elements and the entire composition should be centered in the available space, you could center a single item in the available space and inside that item you could place the items, so that the entire thing is centered regardless of the fact the items are unequal.
Example:
.row {
display: flex;
justify-content: center;
}
.row > * {
margin: 0 auto;
display: flex;
}
.row>*>* {
border: 1px solid #ccc;
text-align: center;
margin: 1rem;
}
<div class="row">
<div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
</div>
<hr>
<div class="row">
<div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
</div>
<hr>
<div class="row">
<div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
</div>
</div>
But, again, that's not something you need flexbox
for.
The exact same can be achieved using a simple parent > child
structure, where parent has display: block; text-align: center;
and children have display: inline-block;
.row {
text-align: center;
}
.row>* {
border: 1px solid #ccc;
text-align: center;
margin: 1rem;
display: inline-block;
}
<div class="row">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<div class="row">
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<div class="row">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
</div>
Notice the absence of the extra wrapper in markup.
Upvotes: 3
Reputation: 56753
Why not simply use a CSS grid for the task? It offers the grid-column-gap
property which does exactly what you need:
.row {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 10px;
}
.column {
border: 1px solid #ccc;
}
h2 {
text-align: center;
}
<div class="row">
<div class="column">
<h2>Centered<br />Text</h2>
</div>
<div class="column">
<h2>Centered<br />Text</h2>
</div>
</div>
Upvotes: 3
Reputation: 471
Try doing this
.column:not(:last-child){
margin-left: 20px;
}
Upvotes: 0