25

I have - let's say - 4 spans on my page in a block. The content of each is populated by knockout from my viewmodel. Sometimes contents are empty for several spans. I would like to display them in a nice, comma-separated way, taking possible emptyness into account.

I tried the following HTML and CSS.

VERSION 1

It shows commas for empty spans as well

.comma:not(:last-child):after {
  content: ", ";
}
<span class="comma">A</span>
<span class="comma">B</span>
<span class="comma"></span>
<span class="comma">D</span>

VERSION 2

It shows a (visually) last comma if last span is empty.

.comma:not(:empty):not(:last-child):after {
  content: ", ";
}
<span class="comma">A</span>
<span class="comma">B</span>
<span class="comma">C</span>
<span class="comma"></span>

How could I tweak it to render always correctly, no matter where the gaps are (if any)? I need to support only modern browsers (IE9+ and others).

Weafs.py
  • 22,731
  • 9
  • 56
  • 78
Zoltán Tamási
  • 12,249
  • 8
  • 65
  • 93

4 Answers4

22

I reversed the logic, placing the comma as the content of before pseudoelement and I managed the case where also the first span can be empty.

.comma:not(:first-child) {
  margin-left: -.3em;  
}

.comma:first-child:empty ~ .comma:not(:empty) {
  margin-left: 0;  
}

.comma:first-child:empty ~ .comma:not(:empty) ~ .comma:not(:empty) {
  margin-left: -.3em;  
}

.comma:empty {
  display: none;
}

.comma:not(:first-child):before {
  content: ", ";
}

.comma:empty + .comma:not(:empty):before {
  content : "";
}

.comma:not(:empty) ~ .comma:empty + .comma:not(:empty):before {
  content : ", ";
}
<div> 
  <span class="comma">A</span>
  <span class="comma">B</span> 
  <span class="comma">C</span>
  <span class="comma">D</span>
</div>

<hr />

<div>
  <span class="comma">A</span>
  <span class="comma">B</span> 
  <span class="comma"></span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma">B</span> 
  <span class="comma">C</span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma">B</span> 
  <span class="comma">C</span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma"></span> 
  <span class="comma">C</span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma">B</span> 
  <span class="comma"></span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma"></span> 
  <span class="comma">C</span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma"></span> 
  <span class="comma"></span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma">B</span> 
  <span class="comma">C</span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma">B</span> 
  <span class="comma"></span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma"></span> 
  <span class="comma">C</span>
  <span class="comma">D</span>
</div>

<div>
  <span class="comma">A</span>
  <span class="comma"></span> 
  <span class="comma"></span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma">B</span> 
  <span class="comma"></span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma"></span> 
  <span class="comma">C</span>
  <span class="comma"></span>
</div>

<div>
  <span class="comma"></span>
  <span class="comma"></span> 
  <span class="comma"></span>
  <span class="comma">D</span>
</div>

<hr />
All empty:
<div>
  <span class="comma"></span>
  <span class="comma"></span> 
  <span class="comma"></span>
  <span class="comma"></span>
</div>

Further information about :empty pseudoclass available on MDN

Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
7

Switch it round. Instead of putting a comma after your spans, put it before each span which is preceded (any distance back!) by a non-empty span:

.comma:not(:empty) ~ .comma:not(:empty):before {
  content: ", ";
}

Fiddle

Chowlett
  • 45,935
  • 20
  • 116
  • 150
  • This leaves that ugly space. – Jack hardcastle Jan 08 '15 at 09:44
  • Combining this with Fabrizio's `margin-left: -.3em;` should do the trick. – Alex Jan 08 '15 at 09:57
  • @Jackhardcastle not if you don't have spaces between html tags ([fiddle](http://jsfiddle.net/9p4x70h8/)). This is just how HTML [works](https://blog.nightly.mozilla.org/2016/10/17/devtools-now-display-white-space-text-nodes-in-the-dom-inspector/). – Mariusz Pawelski Feb 05 '21 at 12:32
0

http://jsfiddle.net/xtrabhwh/3/

<span class="comma">A</span><span class="comma">B</span><span class="comma">C</span><span class="comma"></span>

.comma ~ .comma:not(:empty):before {
    content: ", ";
}
Jack hardcastle
  • 2,748
  • 4
  • 22
  • 40
0

The below should do it, for just about any combination, without hiding anything.

.comma:before {
  content: ','
}
.comma:empty:before,
.comma:first-of-type:before,
.comma:first-of-type+.comma:empty:before,
.comma:empty+.comma:not(:last-of-type):before,
.comma:empty+.comma:empty:before {
  content: '';
}
<h4>Missing first</h4>
<div>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>Missing last</h4>
<div>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>Missing first two</h4>
<div>
  <span class="comma"></span>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>Missing last two</h4>
<div>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma"></span>
</div>
<h4>Missing middle</h4>
<div>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma">item</span>
</div>
<h4>Missing middle two</h4>
<div>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma"></span>
  <span class="comma">item</span>
</div>
SW4
  • 69,876
  • 20
  • 132
  • 137