13

Say I have 3 divs displayed horizontally with flexbox:

 |     |-div1-| |-center-div-| |-wider-div-|     |

And I want the center div to be aligned to the middle of the parent. How can I accomplish this? justify-content will center all 3 of the divs based the sum of all their widths, and applying align-self: center to the middle div does nothing because the align property manipulates positioning on the other axis.

Is there a responsive CSS solution, or should I resort to jQuery?

ul {
    display: flex;
    justify-content: center;
    width: 100%;
    background-color: purple;
}
li {
    background-color: red;
    border: 5px solid blue;
    list-style: none;
}
<ul>
    <li><a href = "#">short</a></li>
    <li><a href = "#">want center</a></li>
    <li><a href = "#">loooooooooooooooooong</a></li>
</ul>

Illustration of this problem: https://jsfiddle.net/7w8mp8Lj/2/

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Brandon Slaght
  • 1,025
  • 1
  • 12
  • 34
  • 1
    This shouldn't be marked duplicate. This is distinct from the one it's marked duplicate of. The solution on the other one will not work for this problem, but the solution @Sitckers gave will work there. – mawburn Jan 10 '20 at 20:58
  • Agreed. This is not a duplicate. The other question is broad. This question is specific. And the search engine found this question, not the other. If we can not search the net and find an answer, how is it helpful? – davidhartman00 May 29 '20 at 14:03

4 Answers4

11

You can set the first and last li to grow flex: 1, and set a as inline block and text align 1/2/3 li as right/center/left.

jsfiddle

ul {
    display: flex;
    justify-content: center;
    width: 100%;
    background-color: purple;
    list-style: none;
    padding: 0;
}
li:nth-child(1) {
    text-align: right;
    flex: 1;
}
li:nth-child(2) {
    text-align: center;
}
li:nth-child(3) {
    text-align: left;
    flex: 1;
}
li a {
    display: inline-block;
    background-color: red;
    border: 5px solid blue;
}
<ul>
    <li><a href="#">short</a></li>
    <li><a href="#">want center</a></li>
    <li><a href="#">loooooooooooooooooong</a></li>
</ul>
Stickers
  • 75,527
  • 23
  • 147
  • 186
4

Here's a flex method that perfectly centers the middle item with:

  • no jQuery
  • no absolute positioning
  • no changes to the HTML

ul {
  display: flex;
  padding: 0;
}
li {
  display: flex;
  justify-content: center;
  flex: 1;
  background-color: red;
  border: 2px solid blue;
}
li:first-child > a {
  margin-right: auto;
}
li:last-child > a {
  margin-left: auto;
}
<ul>
  <li>
    <a href="#">short</a>
  </li>
  <li>
    <a href="#">want center</a>
  </li>
  <li>
    <a href="#">loooooooooooooooooong</a>
  </li>
</ul>

jsFiddle

Here's how it works:

  • The ul is the primary flex container.
  • Each li flex item is given flex: 1 for an equal distribution of container space.
  • Now the lis are consuming all space in the row and are equal width.
  • Make each li a flex container and add justify-content: center
  • Now each anchor element is a centered flex item.
  • Use flex auto margins to shift the outer anchors left and right.
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
2

You can use absolute positioning to take the non-centered items out-of-flow, so that they won't affect the centering.

ul {
  display: flex;
  justify-content: center;
  background-color: purple;
  padding: 0;
  list-style: none;
}
li {
  position: relative;
}
li > a {
  display: block;
  background-color: red;
  border: 5px solid blue;
}
li:first-child > a {
  position: absolute;
  right: 0;
}
li:last-child > a {
  position: absolute;
  left: 0;
}
<ul>
  <li><a href="#">short</a></li>
  <li><a href="#">want center</a></li>
  <li><a href="#">loooooooooooooooooong</a></li>
</ul>

However, note you will lose flexibility because absolutely-positioned children of a flex container do not participate in flex layout (except in the reordering step).

Oriol
  • 274,082
  • 63
  • 437
  • 513
1

I use a flex container with three boxes inside, two of which -- left and right -- have the same width and are flex containers themselves, wrapping the content of arbitrary width:

[(a box)        ]     [centered content]    [    (a longer box)]
  left wrapper                                 right wrapper

Here is the code:

<div class="test">
    <div class="wrapper left">
        <div class="box one"></div>
    </div>
    <div class="box two"></div>
    <div class="wrapper right">
        <div class="box three"></div>
    </div>
</div>

CSS:

.test {
    height: 50px;
    display: flex;
    justify-content: center;
}

.wrapper {
    width: 33%;
    display: flex;
}

.wrapper.left {
    justify-content: flex-end;
}

.box {
    border: 1px solid red;
}

.one {
    width: 100px;
}

.two {
    width: 50px;
}

.three {
    width: 150px;
}
Dima Slivin
  • 599
  • 9
  • 19