Create leading dots in CSS

Css

Css Problem Overview


What is a nice way to do leading dots in a table of contents with CSS?

Example:

Link.............Chapter 1
Link.............Chapter 2
Link.............Chapter 3

Css Solutions


Solution 1 - Css

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 - Css

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 - Css

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:

> 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:

> html > <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 - Css

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 - Css

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;
}

Solution 6 - Css

Many this css hack's don't work with transtarent background or to difficult. You can use modern flex and background-gradient for dotted (it's look more polished, then table dotted). Like this:

.contacts-row {
    display: flex;
    width: 500px;
}

.dots {
    display: block;
    background: radial-gradient(circle, rgba(0,0,0,.62) 1px, transparent 1px) repeat-x;
    background-size: 20px 28px;
    flex-grow: 10;
}

<div class="contacts-row">
    <b>E-mail: </b>
    <span class="dots"></span>
    <span class="text">test@email</span>
</div>

<div class="contacts-row">
     <b>Phone: </b>
     <span class="dots"></span>
     <span class="text">test-phone</span>
</div>

Solution 7 - Css

Acutally the W3C has a working draft describing the functionality you are looking for

http://www.w3.org/TR/css3-gcpm/#leaders

Even back in 2005 A List Apart published an article for it. (http://www.alistapart.com/articles/boom) Unfortunately It doesn't seem to work for me and I haven't found much more. But maybe it's worth keeping it in mind that one day in the near future will be possible with CSS only :)

Solution 8 - Css

Here is my approach, using element with dotted border-style instead of image or content, make it flex and put it between "Link" and "Chapter".

.toc {
  width: 500px;
}

.row {
  flex-direction: row;
  display: flex;
}

.flex-dots {
  border-top-style: dotted;
  border-top-width: 1px;
  max-height: 1px;
  margin-top: 0.5em;
}

.flex-dots-vcenter {
  flex-direction: row;
  display: flex;
}

[flex] {
  flex: 1;
}

    <div class="toc">
      <div class="row">
        <span class="field1">Link 1</span>
        <div class="flex-dots-vcenter" flex><span class="flex-dots" flex></span></div>
        <span class="field2">Chapter 1</span>
      </div>
      <div class="row">
        <span class="field1">Link 20</span>
        <div class="flex-dots-vcenter" flex><span class="flex-dots" flex></span></div>
        <span class="field2">Chapter 20</span>
      </div>
      <div class="row">
        <span class="field1">Link 300</span>
        <div class="flex-dots-vcenter" flex><span class="flex-dots" flex></span></div>
        <span class="field2">Chapter 300</span>
      </div>
    </div>

Solution 9 - Css

Leading dots with CSS grids

.leaders {
  list-style: none;
  margin: 0;
  padding: 0;
}

.leaders li {
  width: 100%;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-gap: 5px;
  justify-items: start;
  align-items: center;
  justify-content: start;
}

.dots {
  border-bottom: 1px dashed #000;
  width: 100%;
}

<ul class="leaders">
  <li>
    <span>Grilled Cheese</span>
    <span class="dots"></span>
    <span>7.95</span>
  </li>
  <li>
    <span>Wonton Soup</span>
    <span class="dots"></span>
    <span>8.95</span>
  </li>
  <li>
    <span>Waffles</span>
    <span class="dots"></span>
    <span>7.95</span>
  </li>
  <li>
    <span>Shrimp Etouffee</span>
    <span class="dots"></span>
    <span>15.25</span>
  </li>
</ul>

Solution 10 - Css

Dot leaders can be be done without spans or classes. Here's a responsive solution for HTML tables, modified to center the dot leader vertically:

http://codepen.io/Paulie-D/pen/bpMyBQ

table {
	width: 90%;
	margin:100px auto;
	table-layout:fixed;
	border-collapse: collapse;
	}

td {
	padding:1em 0 0 0;
	vertical-align:bottom;
	}
	
td span{
   	background-color:#fff;
	}
	
td:first-child {
	text-align: left;
	font-weight: 700;
    overflow: hidden;
    position: relative;
	}
	
td:first-child::after {
    content: '';
    position: absolute;
    bottom: .4em;
    width:1500px;
    height:0px ;
    margin-left: 1em;
    border-bottom:2px dotted grey;
}

td:last-child {
	text-align:right;
	width:3em;
  	}

Solution 11 - Css

I needed to make it easy for my client to edit a price list on their website, so I created the raw content as a simple html table with two columns. This is super easy to edit in any CMS

Then, building on the previous answers and with the goal of being able to handle data formatted as a table, I used the following. I tried the dotted-bottom-border approach, but that is pretty ugly. So I went with the "dots-as-content" approach.

.toc table {
    width: unset;
	margin: 0 auto;
	margin-top: 1ex;
	display: block;
}
.toc  table tbody {
	display: block;
}
.toc  table tr {
	display: flex;
}
.toc  table tr td {
	width: auto !important;
}
.toc  table tr td:first-child {
	order: 1;
	white-space: nowrap;
}
.toc  table tr td:last-child {
	order: 3;
	white-space: nowrap;
}  
.toc  table tr:after {
	flex-grow: 1;
	order: 2;
	content: ". . . . . . . . . . . . . . . . . . . . " 
	". . . . . . . . . . . . . . . . . . . . " 
	". . . . . . . . . . . . . . . . . . . . " 
	". . . . . . . . . . . . . . . . . . . . ";
	white-space: nowrap;
	overflow: hidden;
	text-overflow: clip;
}

<div class="toc">
    <table>
        <tbody>
            <tr>
                <td>
                    Product 1
                </td>
                <td>$123,456</td>
            </tr>
            <tr>
                <td>Product 2</td>
                <td>$12,345</td>
            </tr>
        </tbody>
    </table>
</div>

Solution 12 - Css

Solution 13 - Css

I'm late to the party but we recently had to do this at work and I ended up using a module like this:

http://codepen.io/ryanve/pen/rrBpJq

.dot-leader {
    position: relative;
    overflow: hidden; /* clip the dots */
}

.dot-leader__left {
    position: relative;
    display: inline-block;
}

.dot-leader__left::after {
    color: gray;
    content: ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .";
    font-weight: normal;
    display: inline-block;
    position: absolute;
    white-space: nowrap;
    margin-left: 5px; /* space left of dots */
}

.dot-leader__right {
    background: white; /* cover the dots */
    display: inline-block;
    position: absolute;
    right: 0;
    padding-left: 5px; /* space right of dots */
}

with markup that uses li.dot-leader

<ul class="is-no-padding">
    <li class="dot-leader">
        <span class="dot-leader__left">Pizza</span>
        <span class="dot-leader__right">$100</span>
    </li>
</ul>

or dl.dot-leader

<dl class="dot-leader">
    <dt class="dot-leader__left">Pizza</dt>
    <dd class="dot-leader__right">$100</dd>
</dl>

Solution 14 - Css

None of the other solutions worked for me. Here is my solution which:

  • Respects width of parent divs.
  • Doesn't use white background tricks which don't allow for dynamic environments.
  • Doesn't use a picture of a dot, so the dot can always match the other font colors.
  • Worth both ways and with varying or different values to present

Leader Dots: http://jsfiddle.net/g0d8x8c5/127/

> HTML

<div class="main">

  <p>Example # 1</p>

  <div class="container">
    <div class="row">
      <span>$150</span><span class="dots"></span><span>remaining credit</span>
    </div>
    <div class="row">
      <span class="spacer"></span><span>30</span><span class="dots"></span><span>remaining days</span>
    </div>
  </div>
  
  <p>Example # 2</p>

  <div class="container">
    <div class="row">
      <span>Food Item #1</span><span class="dots"></span><span>$12.95</span>
    </div>
    <div class="row">
      <span>Food Item #22</span><span class="dots"></span><span>$7.95</span>
    </div>
  </div>

</div>

> CSS

.main {
  /* to prove it respects width of outer containers */
  width: 320px;
}

.row {
  display: flex;
}

.dots {
  /* shorthand - flex: 1 1 auto */
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: auto;
  
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
 }
 
 .dots:before {
   content:
    ". . . . . . . . . . . . . . . . . . . . "
    ". . . . . . . . . . . . . . . . . . . . "
    ". . . . . . . . . . . . . . . . . . . . "
    ". . . . . . . . . . . . . . . . . . . . ";
}
 
 .row span:first-child,
 .row span:last-child {
   /* shorthand - flex: 0 0 auto */
   flex-grow: 0;
   flex-shrink: 0;
   flex-basis: auto;
 }
 
.row span:first-child {
   padding-right: 0.33em;
}

 .row span:last-child {
   padding-left: 0.33em;
 }
 
 .spacer {visibility: hidden}
 .spacer:before {content: "$"}

Solution 15 - Css

Great question and great answers.

I found that many of these working answers broke down when alternating background colours are required for the li elements. Here is my contribution which emends this.

Sample list with alternating background items

This is based on nootrope's excellent solution on this page. Their "leaders" class can be re-added if required.

ul{
    padding: 0;
    overflow-x: hidden;
    margin:0 0 24pt;
    list-style: none;
    list-style-type:none;
}
ul li{
	background:white;
}
ul li:nth-child(odd){
	background:lightgrey;
}
ul li:before {
    float:left;
    width:0;
    white-space:nowrap;
    content:
 ". . . . . . . . . . . . . . . . . . . . "
 ". . . . . . . . . . . . . . . . . . . . "
 ". . . . . . . . . . . . . . . . . . . . "
 ". . . . . . . . . . . . . . . . . . . . "
 ". . . . . . . . . . . . . . . . . . . . ";
}
ul span:first-child {
    padding: 0 0.33em 0 0.8em;
    background:inherit;
}
ul span + span{
    float: right;
    padding: 0 0.8em 0 0.33em;
    background:inherit;
}

The main part that makes this work is the careful padding and background:inherit; in the ul span sections.

Note also that adding more of the "filler" dots in ul li:before allows this to stretch to wider elastic layouts.

Hoping that this helps you.

Solution 16 - Css

Just faced this problem for the first time of my >10 years career in frontend. Yay, it's not easy as I thought!

I read all solutions in the web, including this thread, and found nothing I'll like.

Here's my responsive solution using flexbox: https://codepen.io/Grawl/pen/qBXrBWg

demo full width

demo min width

I added animated gradient background to the demo and changed text color to blue to demonstrate that my solution is working without background tricks

The trick I used is with hidden colon after left part:

.optionName-colon {
  position: relative;
  color: transparent;
  display: inline-block;
}

.optionName-colon::after {
  content: "";
  position: absolute;
  top: 0.9em;
  left: 0;
  display: block;
  width: 100em;
  border-bottom: 1px dotted var(--text-color);
}

<div>
  <span class="optionName">
    <span class="optionName-label">Name</span>
  <span class="optionName-colon">:</span>
  </span>
  <strong>Value</strong>
</div>

The leaders is pseudo starting on end of left part and ending in overflow.

So, without CSS it renders like this “Name: Value”, and with CSS it renders like “Name ........ Value”.

Solution 17 - Css

The simplest solution:

<div style="display: flex; width: 20em;">
	<div>Link</div>
	<div style="border-bottom: 1px dotted black ; flex-grow: 1;"></div>
	<div>Chapter1</div>
</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBryan DennyView Question on Stackoverflow
Solution 1 - CssnootropeView Answer on Stackoverflow
Solution 2 - CssRúnar BergView Answer on Stackoverflow
Solution 3 - CssJustin GregoireView Answer on Stackoverflow
Solution 4 - CssNico OView Answer on Stackoverflow
Solution 5 - Csswesty808View Answer on Stackoverflow
Solution 6 - CssDenis SavenkoView Answer on Stackoverflow
Solution 7 - CssF LekschasView Answer on Stackoverflow
Solution 8 - CssOzoneView Answer on Stackoverflow
Solution 9 - CssOnionStandView Answer on Stackoverflow
Solution 10 - CssMichael McGinnisView Answer on Stackoverflow
Solution 11 - CssLászló L. L.View Answer on Stackoverflow
Solution 12 - CssCuteboy_MaxView Answer on Stackoverflow
Solution 13 - CssryanveView Answer on Stackoverflow
Solution 14 - CssAsher GarlandView Answer on Stackoverflow
Solution 15 - CssParapluieView Answer on Stackoverflow
Solution 16 - CssДаниил ПронинView Answer on Stackoverflow
Solution 17 - Csswork79View Answer on Stackoverflow