Using CSS to create a series of spans separated by commas

Imagine having 4 spans arranged in a block on your webpage. These spans are filled with content from a knockout viewmodel, but sometimes they may be empty. How can we display them in a visually appealing, comma-separated format while considering their possible emptiness?

Below are two versions I attempted using HTML and CSS:

VERSION 1

This version displays commas even for empty spans.

.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

In this version, a final comma is displayed if the 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>

Is there a way to modify the code to always render correctly, regardless of where the empty spans are located? It's essential to ensure compatibility with modern browsers like IE9+.

Answer №1

I changed the approach by moving the comma into the before pseudoelement and addressed cases where the first span could 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>

... (additional div/span elements)

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


To learn more about the :empty pseudoclass, visit MDN

Answer №2

Rearrange it. Instead of placing a comma after your spans, place it before each span that is preceded (regardless of distance!) by a non-empty span:

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

Fiddle

Answer №3

http://jsfiddle.net/ywzk78t4/2/

<span class="example">X</span><span class="example">Y</span><span class="example">Z</span><span class="example"></span>

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

Answer №4

This method below can handle any combination without concealing 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>First one missing</h4>
<div>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>Last one missing</h4>
<div>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>First two missing</h4>
<div>
  <span class="comma"></span>
  <span class="comma"></span>
  <span class="comma">item</span>
  <span class="comma">item</span>
</div>
<h4>Last two missing</h4>
<div>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma"></span>
</div>
<h4>Middle one missing</h4>
<div>
  <span class="comma">item</span>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma">item</span>
</div>
<h4>Middle two missing</h4>
<div>
  <span class="comma">item</span>
  <span class="comma"></span>
  <span class="comma"></span>
  <span class="comma">item</span>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

jQuery event triggers upon completion of execution

A custom code has been integrated into my project using jQuery. Check out the code snippet below: <script> $("#startProgressTimer").click(function() { $("#progressTimer").progressTimer({ timeLimit: $("#restTime").val(), onFinish ...

Include previous input as a "phantom" thumbnail to the slider element of type "range"

https://i.stack.imgur.com/JnuCN.png Using a tutorial from w3schools, I have customized a regular range slider. The objective is to send a new value command to an external MQTT-based home automation system and display the previous value as a ghost-thumb in ...

What is the best way to create divs that can close and hide themselves when clicked from inside the div itself?

I have a situation in my code where clicking a link reveals a div, and then the same link must be clicked again to hide it. However, I want to modify this so that any link within the div can also hide it when clicked. I currently have eight divs set up lik ...

Clicking on the menu in mobile view will cause it to slide upward

I have implemented sticky.js on my website and it is working well. However, when I resize the browser to mobile view and click the main menu button, it goes up and I am unable to close it. I have to scroll up to see it again. How can I make it stick to the ...

Create a media query that targets both print and screen devices, specifying a minimum width condition

I am in need of a stylesheet that works well for both print and screens with decent width. When I write the following code, I expect it to be clear: @media print or (screen and (min-width: 801px)) { Rules here } Unfortunately, this code does not ach ...

Understanding the functionality of sessions in CodeIgniter when using AJAX

I am experiencing an issue with the Session in my code. It only works when the page is refreshed. I have a controller called ravi and the view named myview. Here is the code snippet: <?php class Ravi extends CI_Controller { public funct ...

Adjusting the width of a select box to match the size of its child table using CSS

Within my Vue application, I've implemented a select box that contains a table component. When the select box is clicked, the table becomes visible in a container. However, I'm facing an issue where I can't dynamically adjust the width of th ...

Connect Bootstrap Tabs to a pagination system (Backward Forward)

<!DOCTYPE html> <html lang="en"> <head> <title>Bootstrap Example</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://m ...

What is the best way to include multiple font styles for different tags?

While working on a website project, the client requested to use Roboto as the main font (by Google). Different styles of Roboto such as Roboto Thin or Roboto Light were used for various elements on the page. However, I utilized the @font-face selector to e ...

Animate the service item with jQuery using slide toggle effect

Currently, I am working on a jQuery slide toggle functionality that involves clicking an item in one ul to toggle down the corresponding item in another ul. However, I am encountering difficulties in linking the click event to the correct id and toggling t ...

Locate a specific element by utilizing xpath

Recently, I encountered a coding issue that has been puzzling me. Here's the html snippet in question: <div class="Main"> <div> <div class="display">First:</div> <div class="price">$0.01</div> ...

Is there a way to transfer an element from one row to another using Bootstrap?

Can the grid layout transition smoothly from a desktop view to a mobile view using Bootstrap 4 or pure CSS flex classes? Desktop view: Mobile view : Currently, I have a solution in place but I want to avoid repeating content in two different places. Is ...

Is it possible to reposition the vertical scrollbar to a location that is not on the left or right side?

Whenever I resize my modal on small screens, a horizontal scrollbar appears, causing the vertical scrollbar to disappear as it gets stuck on the right side. I am looking for a solution to keep the vertical scrollbar on the right side of the modal while scr ...

The canvas element on a simple HTML webpage is constantly set to a size of 300x150

In an attempt to simplify my problem, I have created a basic HTML document with a <canvas> element: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body { border: 1px solid #ff5500; ...

What is causing my page to automatically refresh whenever I click on buttons?

The code snippet below shows the structure of my webpage : HTML : <button class="add-col"><i class="fas fa-columns"> Add a column</i></button> <div class="table-responsive"> <table class="table"> ...

The outline color cannot be removed from vue-carousel

I recently downloaded the Vue Carousel library and here is the version I am using: "vue": "^2.6.11", "vue-carousel": "^0.18.0", When I click on the pagination, a focus effect is added to the element with an outlin ...

Eliminate excess spacing to the right of input fields

I've been attempting to configure a flexbox layout with multiple input fields, but I'm having trouble achieving the desired look. Here is the code snippet that I've been working with: .inputSettings { display: flex; flex-direction: ro ...

Trying to align a Material UI button to the right within a grid item

I'm attempting to right float the button below using material-ui, but I'm unsure of how to achieve this: <Grid item xs={2}> <Button variant="contained" color="secondary&quo ...

How can I activate a disabled option number 2 after selecting option number 1?

I have encountered an issue with my JavaScript code. The second "select" element is supposed to be disabled by default, but I want it to become enabled when an option is selected from the first "select". However, this functionality is not working as expect ...

Is there a method to instruct angular-cli (for angular 2) to produce a minified version of css files?

When running "ng serve" in angular-cli, the generated css is not minified as expected. Is there a specific setting to configure in angular-cli-build or an additional plugin to install? This is the content of my angular-cli-build.js file: var Angular2App ...