How to Add Commas Between a List of Items Dynamically with CSS

Avatar of Dave Seidman
Dave Seidman on

Take your JavaScript to the next level at Frontend Masters.

Imagine you have a list of items. Say, fruit: Banana, Apple, Orange, Pear, Nectarine

We could put those commas (,) in the HTML, but let’s look at how we could do that in CSS instead, giving us an extra level of control. We’ll make sure that last item doesn’t have a comma while we’re at it.

I needed this for a real project recently, and part of the requirements were that any of the items in the list could be hidden/revealed via JavaScript. The commas needed to work correctly no matter which items were currently shown.

One solution I found rather elegant solution is using general sibling combinator. We’ll get to that in a minute. Let’s start with some example HTML. Say you start out with a list of fruits:

<ul class="fruits">
  <li class="fruit on">Banana</li>
  <li class="fruit on">Apple</li>
  <li class="fruit on">Orange</li>
  <li class="fruit on">Pear</li>
  <li class="fruit on">Nectarine</li>
</ul>

And some basic CSS to make them appear in a list:

.fruits {
  display: flex;
  padding-inline-start: 0;
  list-style: none;
}

.fruit {
  display: none; /* hidden by default */
} 
.fruit.on { /* JavaScript-added class to reveal list items */
  display: inline-block;
}

Now say things happen inside this interface, like a user toggles controls that filter out all fruits that grow in cold climates. Now a different set of fruits is shown, so the fruit.on class is manipulated with the classList API.

So far, our HTML and CSS would create a list like this:

BananaOrangeNectarine

Now we can reach for that general sibling combinator to apply a comma-and-space between any two on elements:

.fruit.on ~ .fruit.on::before {
  content: ', '; 
}

Nice!

You might be thinking: why not just apply commas to all the list items and remove it from the last with something like :last-child or :last-of-type. The trouble with that is the last child might be “off” at any given time. So what we really want is the last item that is “on,” which isn’t easily possible in CSS, since there is nothing like “last of class” available. Hence, the general sibling combinator trick!

In the UI, I used max-width instead of display and toggled that between 0 and a reasonable maximum value so that I could use transitions to push items on and off more naturally, making it easier for the user to see which items are being added or removed from the list. You can add the same effect to the pseudo-element as well to make it super smooth.

Here’s a demo with a couple of examples that are both slight variations. The fruits example uses a hidden class instead of on, and the veggies example has the animations. SCSS is also used here for the nesting:

I hope this helps others looking for something similar!