Keep the Middle Item Centered When Side Items Have Different Widths

Keep the middle item centered when side items have different widths

If the left and right boxes would be exactly the same size, I get the desired effect. However when one of the two is a different size the centered box is not truly centered anymore. Is there anyone that can help me?

Here's a method using flexbox to center the middle item, regardless of the width of siblings.

Key features:

  • pure CSS
  • no absolute positioning
  • no JS/jQuery

Use nested flex containers and auto margins:

.container {  display: flex;}.box {  flex: 1;  display: flex;  justify-content: center;}
.box:first-child > span { margin-right: auto; }
.box:last-child > span { margin-left: auto; }
/* non-essential */.box { align-items: center; border: 1px solid #ccc; background-color: lightgreen; height: 40px;}p { text-align: center; margin: 5px 0 0 0;}
<div class="container">  <div class="box"><span>short text</span></div>  <div class="box"><span>centered text</span></div>  <div class="box"><span>loooooooooooooooong text</span></div></div><p>↑<br>true center</p>

How to center the middle item in a flex row?

The primary way to achieve this layout – because it's clean and valid – is with flex: 1 on the items. That method is explained in the following post, but is also ruled out in this question.

  • Keep the middle item centered when side items have different widths

An alternative method involves CSS absolute positioning:

.parentContainer {  display: flex;  justify-content: space-between;  position: relative;}
.middle { position: absolute; left: 50%; transform: translateX(-50%);}
/* non-essential decorative styles */.parentContainer > * { background: orange; text-align: center; padding: 5px; }p { text-align: center;}p > span { background-color: aqua; padding: 5px; }P > span:first-child { font-size: 1.5em; }
<div class="parentContainer">  <div class="left">small</div>  <div class="middle">medium element here</div>  <div class="right">longer element is here too</div></div><p>  <span>↑</span><br>  <span>true center</span></p>

Horizontally distribute elements of varied width while keeping the middle item centered

One possible solution would be to break the container into three flex children; left, center, and right.

To keep the center anchored, apply flex: 1; to left and right.

To get even space on the last child of left, and the first child of right, you can add an empty block psuedo-element.

#container {  display: flex;  justify-content: space-between;}
#container>div { display: flex; justify-content: space-between;}
#container>div.left,#container>div.right { flex: 1;}
#container>div.left::after,#container>div.right::before { display: block; content: '';}
#container>div>div { background-color: black;}
#container>div.left>div:nth-child(1) { width: 100px; height: 20px;}
#container>div.left>div:nth-child(2) { width: 80px; height: 30px;}

#container>div.center>div { width: 50px; height: 50px;}
#container>div.right>div:nth-child(1) { width: 40px; height: 30px;}
#container>div.right>div:nth-child(2) { width: 90px; height: 10px;}
p { width: 100%; text-align: center;}
<div id="container">  <div class="left">    <div></div>    <div></div>  </div>  <div class="center">    <div></div>  </div>  <div class="right">    <div></div>    <div></div>  </div></div><p>  ↑<br> actual center</p>

Center a flex item in a row when there are a different number of items on each side

Flexbox

Use 7 items.

One in the center.

Each side has 3.

Hide one on the right with visibility: hidden.

If you don't want to add a fake item in the DOM, then use a pseudo-element instead, also with visibility: hidden.

More details here:

  • Center and right align flexbox elements
  • How can you keep the center box centered in a flex box layout?

Grid

If you're open to another CSS3 technology, you can avoid the flexbox hacks above. Here's a clean and valid solution using Grid:

ul {  display: grid;  grid-template-columns: repeat(7, 1fr);  grid-template-rows: 50px;  grid-gap: 10px;  grid-template-areas: " item1 item2 item3 item4 ... item5 item6 ";}
li:nth-child(1) { grid-area: item1; }li:nth-child(2) { grid-area: item2; }li:nth-child(3) { grid-area: item3; }li:nth-child(4) { grid-area: item4; }li:nth-child(5) { grid-area: item5; }li:nth-child(6) { grid-area: item6; }
/* non-essential demo styles */p { text-align: center;}span { background-color: yellow; padding: 5px;}li { display: flex; align-items: center; justify-content: center; color: white; background-color: black;}ul { background-color: red; list-style: none; margin: 0; padding: 10px;}
<ul>  <li>Item 1</li>  <li>Item 2</li>  <li>Item 3</li>  <li>Item 4</li>  <li>Item 5</li>  <li>Item 6</li></ul><p><span>TRUE CENTER</span></p>

Centering one flex item and and aligning second item to right by any amount of px

You can use width: 0; white-space: nowrap; trick.