Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Center a flex item when its siblings have different widths [duplicate]

I know flexbox offers a great solution for centering items. But I run into an issue when I have 3 items and I'd like the center (2nd) item to be centered with respect to the window, regardless of the size of the other 2 items.

In my pen you can see the second item "Client Index" is off-center because the content on the right is larger than the content on the left. How can I force it to center itself?

.flex {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
<div class="flex">
  <span style="font-size:12px;">small</span>
  <span style="font-size:20px;">Client Index</span>
  <span style="font-size:18px;">Lots of content that moves the center</span>
</div>

My Codepen

like image 545
Jeremy Thomas Avatar asked Jun 06 '17 19:06

Jeremy Thomas


2 Answers

One way would be to set flex-grow: 1; flex-basis: 0 so the 3 columns are distributed evenly, then you can center the text or the content in the middle one.

I'm using text-align to center the middle column. You could also use display: flex; justify-content: center; to do the same thing.

.flex { 
  display: flex; 
  align-items: center;
  justify-content: space-between;
}
.flex > span {
  flex: 1 0 0;
}
.flex > span:nth-child(2) {
  text-align: center;
}
<div class="flex">
  <span style="font-size:12px;">small</span>
  <span style="font-size:20px;">Client Index</span>
  <span style="font-size:18px;">Lots of content that moves the center</span>
</div>
like image 184
Michael Coker Avatar answered Oct 23 '22 18:10

Michael Coker


Use nested flex containers and auto margins.

.flex-container {
  display: flex;
}

.flex-item {
  flex: 1;
  display: flex;
  justify-content: center;
}

.flex-item:first-child>span {
  margin-right: auto;
}

.flex-item:last-child>span {
  margin-left: auto;
}

/* non-essential */
.flex-item {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
<div class="flex-container">
  <div class="flex-item"><span>short</span></div>
  <div class="flex-item"><span>medium</span></div>
  <div class="flex-item"><span>lonnnnnnnnnnnnnnnnnnnng</span></div>
</div>

Here's how it works:

  • The top-level div is a flex container.
  • Each child div is now a flex item.
  • Each item is given flex: 1 in order to distribute container space equally.
  • Now the items are consuming all space in the row and are equal width.
  • Make each item a (nested) flex container and add justify-content: center.
  • Now each span element is a centered flex item.
  • Use flex auto margins to shift the outer spans left and right.

You could also forgo justify-content and use auto margins exclusively.

But justify-content can work here because auto margins always have priority. From the spec:

8.1. Aligning with auto margins

Prior to alignment via justify-content and align-self, any positive free space is distributed to auto margins in that dimension.

like image 31
Michael Benjamin Avatar answered Oct 23 '22 17:10

Michael Benjamin