2

I have some cosmetic content which I would like to align between flex items which are justified with space-between.

The items have dynamic width.

The result in the following demo is what i'm looking for, except that since the content is purely cosmetic - I want to use generated content for them rather than actual elements.

ul {
  display: flex;
  justify-content: space-between;
  align-items: center;
  
  list-style: none;
  padding: 0;
}
li:nth-child(odd) {
  background-color: lime;
  padding: 10px 20px
}
li:nth-child(even) {
  margin: 0 auto;
}
<ul class="wpr">
  <li>this is item 1</li>
  <li>X</li>
  <li>item 2</li>
  <li>X</li>
  <li>item 3 is considerably wider</li>
  <li>X</li>
  <li>item 4</li>
</ul>

Codepen demo (resize to see the effect)

I have attempted to do this by using absolute positioning - but I don't know if there is a mechanism to center the content between the items this way:

ul {
  display: flex;
  justify-content: space-between;
  align-items: center;
  
  list-style: none;
  padding: 0;
}
li {
  background-color: lime;
  padding: 10px 20px;
  position: relative;
}
li:after {
  content: 'X';
  position: absolute;
  right: -50%; /* this obviously won't produce the correct centering */
}
<ul class="wpr">
  <li>this is item 1</li>
  <li>item 2</li>
  <li>item 3 is considerably wider</li>
  <li>item 4</li>
</ul>

Is it possible with CSS to add this content using generated content instead of actual elements?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Danield
  • 121,619
  • 37
  • 226
  • 255
  • I'm not sure what you are asking, does the demo describe the behavior you are trying to achieve ?, if yes than what is the problem, if not than what should be different ? – MichaelB Mar 06 '18 at 13:25
  • you want to generate the X with CSS ? – Temani Afif Mar 06 '18 at 13:26
  • @MichaelB in the demo - I have used actual elements in the markup for the X - I want to use generated content for this – Danield Mar 06 '18 at 13:27
  • @TemaniAfif yes, and I want it to be horizontally centered between the items – Danield Mar 06 '18 at 13:28
  • intresting, i suppose you want them to be any kind of elements ? maybe an icon or image ? – Temani Afif Mar 06 '18 at 13:30
  • @TemaniAfif - yes, the 'X' is just for demo purposes - not the real design which i'm implementing ;) ... you see, it really makes no sense to add these cosmetic items in the markup... – Danield Mar 06 '18 at 13:31

3 Answers3

1

Here is an idea with a small drawback because I had to omit the item in the last li:

ul {
  display: flex;
  justify-content: space-between;
  align-items: center;
  list-style: none;
  padding: 0;
}

li {
  display: flex;
  align-items:center;
  flex:1;
}

li span {
  background-color: lime;
  padding: 10px 20px;
  white-space:nowrap;
}

li:after {
  content: "X";
  flex: 1;
  text-align:center;
}
li:last-child {
 flex:initial;
}
li:last-child::after {
 content:none;
}
<ul class="wpr">
  <li><span>this is item 1</span></li>
  <li><span>item 2</span></li>
  <li><span>item 3 is considerably wider</span></li>
  <li><span>item 4</span></li>
</ul>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

You can do it cleanly and efficiently with absolute positioning:

ul {
  display: flex;
  align-items: center;
  list-style: none;
  padding: 0;
}

li {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 10px 20px;
  border: 1px dashed red;
  position: relative;
}

li + li::before {                /* #1 */
  content: "X";
  position: absolute;
  right: 100%;
  transform: translateX(50%);   /* #2 */
}
<ul class="wpr">
  <li>this is item 1</li>
  <li>item 2</li>
  <li>item 3 is considerably wider</li>
  <li>item 4</li>
</ul>

revised codepen

Notes:

  1. The adjacent sibling combinator (+) targets an element that immediately follows another element. In this case, the pseudo-element will only apply to li elements that follow another li. This will naturally exclude the ::before from the first li.

  2. For an explanation of how this centering method works, see this post: Element will not stay centered, especially when re-sizing screen

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • +1 - I like that your answer doesn't necessitate adding extra markup, however the result isn't exactly like I wanted - with the items being justified with space between. – Danield Mar 07 '18 at 07:49
  • 1
    I removed `justify-content` because it's not doing anything. It's not doing anything in your accepted answer either. Once you set `flex-grow` on a flex item (as you have done with `flex: 1`), it consumes all space on the line. Hence, `justify-content` is rendered useless because it has no free space to align. – Michael Benjamin Mar 07 '18 at 15:34
  • Also, you don't even need `justify-content: space-between`. You can achieve the same effect with `flex: 1` on the items, then aligning the content within each one. See my answer here for an example https://stackoverflow.com/q/32378953/3597276 – Michael Benjamin Mar 07 '18 at 17:03
0

One improvement i can suggest is replacing

li:after {
  content: "X";
  flex: 1;
  text-align:center;
}
li:last-child {
 flex:initial;
}
li:last-child::after {
 content:none;
}

with

li:not(:last-child)::after {
      content: "X";
      flex: 1;
      text-align:center;
    }
MichaelB
  • 1,332
  • 1
  • 15
  • 29