Aligning elements left and center with flexbox

I'm using flexbox to align my child elements. What I'd like to do is center one element and leave the other aligned to the very left. Normally I would just set the left element using margin-right: auto. The problem is that pushes the center element off center. Is this possible without using absolute positioning?

HTML & CSS

#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
width: 500px;
}
#left {
margin-right: auto;
}
#center {
margin: auto;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>

68124 次浏览

EDIT: See Solo's answer below, it is the better solution.


The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.

As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.


If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:

#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}

If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element: Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)

#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: space-between;
margin: 0 auto;
width: 500px;
}
#right {
opacity: 0;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Left</span>
</div>

As far as I know this is possible with the following code.

https://jsfiddle.net/u5gonp0a/

.box {
display: flex;
justify-content: center;
background-color: green;
text-align: left;
}


.left {
padding: 10px;
background-color: pink;
}


.center {
padding: 10px;
background-color: yellow;
margin: 0 auto;
}
<div class="box">
<div class="left">left</div>
<div class="center">center</div>
</div>

If you don't want to rely on positioning, the only way I've found that makes it truly centered is to use a combination of auto margin and negative margin prevent the centered element to getting pushed over by the left aligned element. This requires that you know the exact width of the left aligned element though.

.container {
height: 100px;
border: solid 10px skyblue;
  

display: flex;
justify-content: center;
}


.block {
width: 120px;
background: tomato;
}


.justify-start {
margin-right: auto;
}


.justify-center {
margin-right: auto;
margin-left: -120px;
}
<div class="container">
<div class="block justify-start"></div>
<div class="block justify-center"></div>
</div>

Try this no hacks :)

CSS

.container{
width: 500px;
margin: 0 auto;
}
.box{
display: flex;
align-items: center;/* just in case*/
justify-content: space-between;
}
.box p:nth-child(2){
text-align: center;
background-color: lime;
flex: 1 1 0px;
}

HTML

<div class="container">
<div class="box">
<p>One</p>
<p>Two</p>
</div>
</div>

http://codepen.io/whisher/pen/XpGaEZ

Add third empty element:

<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>

And the following style:

.parent {
display: flex;
}
.left, .right {
flex: 1;
}

Only left and right are set to grow and thanks to the facts that...

  • there are only two growing elements (doesn't matter if empty) and
  • that both get same widths (they'll evenly distribute the available space)

...center element will always be perfectly centered.

This is much better than accepted answer in my opinion because you do not have to copy left content to right and hide it to get same width for both sides, it just magically happens (flexbox is magical).


In action:

.parent {
display: flex;
}


.left,
.right {
flex: 1;
}




/* Styles for demonstration */
.parent {
padding: 5px;
border: 2px solid #000;
}
.left,
.right {
padding: 3px;
border: 2px solid red;
}
.center {
margin: 0 3px;
padding: 3px;
border: 2px solid blue;
}
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>

.parent {
display: flex;
}


.left {
flex: 1;
}


.parent::after {
flex: 1;
content: '';
}
<div class="parent">
<div class="left">Left</div>
<div>Center</div>
</div>

I have another solution. In my opinion, Adding an empty block to the center element is fine but code-wise it bit ugly.

Since this is 4 years old I figured I'd update this with a much easier CSS Grid solution.

#parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1px solid black;
margin: 0 auto;
width: 500px;
}
#center {
text-align: center;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>

If you have a grid system you can use it to do what you want without "extra" css.

Below with bootstrap (V 4.X)
Note: It uses flex under the hood

<div class="row">
<div class="col text-left">left</col>
<div class="col text-center">center</col>
<div class="col text-right">right</col>
</div>

Doc bootstrap: https://getbootstrap.com/docs/4.6/layout/grid/

Et voilà ! :)

Solution 1: give 50% width to center element and use justify-content:space-between

#parent {
display: flex;
justify-content: space-between;
}


#center {
flex-basis: 50%;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>

Solution 2: Add one dummy element and hide it.

#parent {
display: flex;
justify-content: space-between;
}


#right {
visibility:hidden;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Right</span>
</div>