Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Horizontally center flex item between 2 flex items of different widths [duplicate]

Tags:

html

css

flexbox

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/

like image 247
Timestretch Avatar asked Oct 22 '15 17:10

Timestretch


3 Answers

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>
like image 141
Stickers Avatar answered Oct 29 '22 05:10

Stickers


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.
like image 28
Michael Benjamin Avatar answered Oct 29 '22 05:10

Michael Benjamin


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).

like image 38
Oriol Avatar answered Oct 29 '22 05:10

Oriol