Add dividing line between flex items with equal space distribution

I think the only way to accomplish this with flexbox is to wrap the text in a new element, as @Kukkuz has done in another answer.

Without that extra wrapper, you can still get the equal spaced dividers, but the red background isn't confined to the length of the text.

Below is an example with:

  • No changes to the HTML.
  • No need for pseudo elements.
  • No need for absolute positioning.

If a background color for the text isn't necessary, then remove it and this should be all you need.

.Flex {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}
.Flex-item {
  flex: 1 1 auto;
  background: red;
}
.Flex-item {
  text-align: center;
}
.Flex-item:first-child {
  text-align: left;
}
.Flex-item:last-child {
  text-align: right;
}
.Flex-item + .Flex-item {
  border-left: 1px solid white;
}
.Container {
  max-width: 70%;
  margin-right: auto;
  margin-left: auto;
  background: blue;
  padding-top: 20px;
  padding-bottom: 20px;
}
<div class="Container">
  <ul class="Flex">
    <li class="Flex-item">Lorem</li>
    <li class="Flex-item">consectetur</li>
    <li class="Flex-item">vestibulum</li>
    <li class="Flex-item">nec</li>
    <li class="Flex-item">condimentum</li>
  </ul>
</div>

If you can add a span around the text, which will allow you to limit the red background to the length of the text, then you're all set:

.Flex {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}
.Flex-item {
  flex: 1 1 auto;
  display: inline-flex;
  justify-content: center;
}
.Flex-item span {
    background-color: red;
}
.Flex-item:first-child span {
  margin-right: auto;
}
.Flex-item:last-child span {
  margin-left: auto;
}
.Flex-item + .Flex-item {
  border-left: 1px solid white;
}
.Container {
  max-width: 70%;
  margin-right: auto;
  margin-left: auto;
  background: blue;
  padding-top: 20px;
  padding-bottom: 20px;
}
<div class="Container">
  <ul class="Flex">
    <li class="Flex-item"><span>Lorem</span></li>
    <li class="Flex-item"><span>consectetur</span></li>
    <li class="Flex-item"><span>vestibulum</span></li>
    <li class="Flex-item"><span>nec</span></li>
    <li class="Flex-item"><span>condimentum</span></li>
  </ul>
</div>

Instead of :after use a stylistic, ARIA representational LIs

<li class="separator" aria-hidden="true" role="presentation"></li>

like:

.Container {
  max-width: 70%;
  margin: 0 auto;
  background: blue;
}

.Flex {
  display: flex;
  justify-content: space-between;
  list-style: none; padding: 20px 0; margin:0;
}

.Flex-item {
  background: red;
}

.separator {
  background: white; width: 1px;
}
<div class="Container">
  <ul class="Flex">
    <li class="Flex-item">Lorem</li>
    <li class="separator" aria-hidden="true" role="presentation"></li>
    <li class="Flex-item">consectetur</li>
    <li class="separator" aria-hidden="true" role="presentation"></li>
    <li class="Flex-item">vestibulum</li>
    <li class="separator" aria-hidden="true" role="presentation"></li>
    <li class="Flex-item">nec</li>
    <li class="separator" aria-hidden="true" role="presentation"></li>
    <li class="Flex-item">condimentum</li>
  </ul>
</div>

P.S: yes, I tried using display: list-item initially on the :after pseudo but naah.


I'm using this solution on a project I'm working on.

It sets justify-content: space-between; on the flex container and flex: 1 1 auto; on the children with a left border on all childrens except first.

I modified your example CSS so you can have a look. I wasn't sure if you were going to have background color on the children so I just used line-height to get larger borders.

html {
    box-sizing: border-box;
}

.Container {
    max-width: 70%;
    margin-right: auto;
    margin-left: auto;
    background: blue;
    padding-top: 20px;
    padding-bottom: 20px;
}

.Flex {
    display: flex;
    flex-flow: row wrap;
    justify-content: space-between;
    list-style: none;
    margin: 0;
    padding: 0;
}

.Flex-item {
    flex: 1 1 auto;
    background: red;
    position: relative;
    text-align: center;
    line-height: 40px;
}

.Flex-item + .Flex-item {
    border-left: solid 1px white;
}

/** Optional for OPs exact layout */

.Flex-item:first-child {
    text-align: left;
}

.Flex-item:last-child {
    text-align: right;
}
<div class="Container">
    <ul class="Flex">
        <li class="Flex-item">Lorem</li>
        <li class="Flex-item">consectetur</li>
        <li class="Flex-item">vestibulum</li>
        <li class="Flex-item">nec</li>
        <li class="Flex-item">condimentum</li>
    </ul>
</div>

No modification to HTML.


You can make it work by using a nested flexboxes - I understand you can't change the markup, but at least you have to wrap the contents of the li into a span like I have here:

  1. Make .flex-item also a flexbox with the text in a span (this would have the red background now) and the separator as an :after element

  2. Apply flex-grow and flex-shrink to 1 and flex-basis to auto for the Flex-item.

  3. The flex: 0 to the last Flex-item and margin-auto to the :after also contributes to the effect.

A demo may explain it better - see below:

html {
  box-sizing: border-box;
}
.Container {
  max-width: 70%;
  margin-right: auto;
  margin-left: auto;
  background: blue;
  padding-top: 20px;
  padding-bottom: 20px;
}
.Flex {
  display: flex;
  justify-content: space-between;
  list-style: none;
  margin: 0;
  padding: 0;
}
.Flex-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex: 1 1 auto;
}
.Flex-item span {
  background: red;
}
.Flex-item:not(:last-child):after {
  content: "";
  border: 1px solid white;
  height: 40px;
  margin: auto;
}
.Flex-item:last-child {
  flex: 0;
}
<div class="Container">
  <ul class="Flex">
    <li class="Flex-item">
      <span>Lorem</span>
    </li>
    <li class="Flex-item">
      <span>consectetur</span>
    </li>
    <li class="Flex-item">
      <span>vestibulum</span>
    </li>
    <li class="Flex-item">
      <span>nec</span>
    </li>
    <li class="Flex-item">
      <span>condimentum</span>
    </li>
  </ul>
</div>

Tags:

Html

Css

Flexbox