Create leading dots in CSS

Solution 1:

This is the best CSS-only solution I have found for this issue of dot leaders:

http://www.w3.org/Style/Examples/007/leaders.en.html

HTML

<ul class="leaders">
 <li><span>Salmon Ravioli</span> <span>7.95</span></li>
 <li><span>Fried Calamari</span> <span>8.95</span></li>
 <li><span>Almond Prawn Cocktail</span> <span>7.95</span></li>
 <li><span>Bruschetta</span> <span>5.25</span></li>
 <li><span>Margherita Pizza</span> <span>10.95</span></li>
</ul>

CSS2/CSS3

ul.leaders {
max-width: 40em;
padding: 0;
overflow-x: hidden;
list-style: none
}

ul.leaders li:before {
float: left;
width: 0;
white-space: nowrap;
content:
". . . . . . . . . . . . . . . . . . . . "
". . . . . . . . . . . . . . . . . . . . "
". . . . . . . . . . . . . . . . . . . . "
". . . . . . . . . . . . . . . . . . . . "
}

ul.leaders span:first-child {
padding-right: 0.33em;
background: white
}

ul.leaders span + span {
float: right;
padding-left: 0.33em;
background: white
}

We create the dot leaders with a ‘:before’ pseudo-element attached to the LI elements. The pseudo-element fills the whole width of the list item with dots and the SPANs are put on top. A white background on the SPANs hides the dots behind them and an ‘overflow: hidden’ on the UL ensures the dots do not extend outside the list.

I used an arbitrary 80 dots, which is enough to fill about 38em, hence the maximum width on the list.

Solution 2:

Building up on @Nico O‘s answer, there is no need for the un-semantic .dots element.

.toc li {
  display: flex;
}

.toc li .title {
  order: 1;
}

.toc li .chapter {
  order: 3;
}

.toc li::after {
  background-image: radial-gradient(circle, currentcolor 1px, transparent 1.5px);
  background-position: bottom;
  background-size: 1ex 4.5px;
  background-repeat: space no-repeat;
  content: "";
  flex-grow: 1;
  height: 1em;
  order: 2;
}
<ul class="toc">
  <li>
    <span class="title">Foo</span>
    <span class="chapter">Chapter 1</span>
  </li>
  <li>
    <span class="title">Bar</span>
    <span class="chapter">Chapter 2</span>
  </li>
</ul>

We take advantage of the fact that we can order the children of our flex container however we want, and the fact that a pseudo element behaves like a child of where it was defined. The key is the flex-grow rule. a flex-grow of 1 while all other siblings have the default 0 will grow to the remaining space even though it has no content.

This will work until the .title and .chapter elements together fill all the space. Then the ::after pseudo element will have a width of 0 and the dotted border won’t be displayed, even though the .title and .chapter will wrap their content. So if you’re sure that won’t happen, and your viewers use modern browsers this might be the optimal solution.

We create the dots using a radial-gradient background. We space repeat the background along the x-axis (background-repeat: space no-repeat) to prevent any dot from being clipped at the middle and positioned on the bottom. The background size is three times as wide as the dot to create adequate space between them. Also note that we add some blur around the edge of each dot (0.5px) for anti-aliasing.

Kudos to @Denis Savenko for coming up with using radial gradient to create the dots in a different answer.

Solution 3:

Taken from this article on Leader Dots with CSS:

The field label is wrapped in a div which has a small image of a dot applied repeatedly in the x direction as a background. This alone would cause the dots to flow under the text. So to nullify that effect, the text itself is then wrapped in a span where the background color is set to match the color of the background of the containing element.

Here is the CSS:

.dots { 
  background: url('dot.gif') repeat-x bottom; 
}
.field {
  background-color: #FFFFFF;
} 

To apply this to the example form, you would just use it as:

<div class="dots">
    <span class="field">LastName</span>
</div>

Here's a image to use for the dot: https://i.stack.imgur.com/otJN0.png

Demo in Stack Snippets

.dots { 
  background: url('https://i.stack.imgur.com/otJN0.png') repeat-x bottom; 
}
.field {
  background-color: #FFFFFF;
}
.link {
  width: 150px;
  display: inline-block;
}
<div class="row">
  <div class="dots link">
      <span class="field">Link</span>
  </div>
  <span class="chapter">
      Chapter 1
  </span>
</div>

<div class="row">
  <div class="dots link">
      <span class="field">Link</span>
  </div>
  <span class="chapter">
      Chapter 2
  </span>
</div>

<div class="row">
  <div class="dots link">
      <span class="field">Link</span>
  </div>
  <span class="chapter">
      Chapter 3
  </span>
</div>

Solution 4:

It is possible to combine the classic technique of "leaders" described by the w3c Thanks to @nootrope with the joy of flexbox.

Here is an alternative approach, for Modern Browsers and IE 10+.

Demo: http://jsfiddle.net/tbm62z6L/2/

.article {
   display: flex;
 }
 .article .item,
 .article .price {
   flex: 1 0 auto;
 }
 .article .dots {
   flex: 0 1 auto;
   /*Allows too long content to be hidden.*/
   overflow: hidden;
 }
 .dots::before {
   display: block;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: clip;
   content: 
     ". . . . . . . . . . . . . . . . . . . . "
     ". . . . . . . . . . . . . . . . . . . . "
     ". . . . . . . . . . . . . . . . . . . . "
     ". . . . . . . . . . . . . . . . . . . . "
 }
<div class="article">
  <span class="item">sandwichtoaster</span>
  <span class="dots"></span>
  <span class="price">$35</span>
</div>

This is a very flexible way to display leading dots, using the current font and no need to use images.

Solution 5:

I mashed-up a couple examples to create what I think is a pretty good solution. Doesn't rely on background color to hide the leader dots. Works on IE8 too.

http://jsfiddle.net/westy808/g0d8x8c5/1/

<ul class="leaders">
    <li><span>Item</span><span>12.234</span></li>
    <li><span>Another Item</span><span>1,000.25</span></li>
</ul>

ul.leaders li { clear: both; }

ul.leaders li span:first-child {
    float: left;
    padding: 0 .4em 0 0;
    margin: 0;
}
ul.leaders li span + span {
    float: right;
    padding: 0 0 0 .4em;
    margin: 0;
}

ul.leaders li:after {
    content: "";
    display: block;
    overflow: hidden;
    height: 1em;
    border-bottom: 1px dotted;
}