Skip to main content
Responsive Web Typography
Friday, 22 November, 2019

Conjuring up a better numbered list

One thing I’ve ended up doing on several projects lately—including my own site—is to style ordered (and unordered) lists with a slightly different approach than in the past. It’s always been frustrating that by default you can’t style the numbers or bullets all that much. You can specify a few different list styles, but you can’t change color or font. I decided to dig in to that and found a couple of helpful posts about it and started to come up with an approach that I thought would work. 

A nicer numbered list from the book 'Counter punch'
Even just setting the numbers with a full stop after them like those in Fred Smeijers’ wonderful tome Counterpunch isn’t possible without pulling out a few tricks in CSS. But never fear—we’ve got this

Typographically, the goal was to come up with a way to style the typeface, background, color, and spacing of the numbers or bullets. It had to work both aesthetically and functionally, meaning that accessibility via screen readers and other assistive technologies was an absolute must. The ability to style numbers and bullets would mean you can use a combination of typefaces or weights, use color to accentuate or decrease the visual weight of the list elements, or even add backgrounds to numbers for a much greater visual impact.

What came together to make this possible was a combination of CSS capabilities like counters and generated content. With a bit of testing it has proved to be pretty resilient, and seems to work just as well as the normal list styles from an accessibility standpoint. Thanks to some inspiration and exploration by the likes of Cassie Evans and Eric Meyer, it feels like a perfect use of CSS techniques layered together to solve the challenge.

Counting backwards (and by letter)

CSS counters have been around for quite some time, but somehow have never come up in my work until recently. But the ability to create counters and iterate on them through repeating elements like counters or sets of grid block items can be extremely useful. Let’s take a look at how they work.

A fancy numbered list
A nested ordered list showing alternate font and color for the list numbers and letters

The first thing you have to do is define the counter on the containing elements (in this case, the ‘ol’ element that contains the ordered list items.

ol {
  list-style: none;
  /* name the counter */
  counter-reset: list-counter; 

Then you set the increment on the list item style, and the rest takes care of itself. You can also nest them and the counter will increment properly at each level. This is particularly useful on nested lists like outlines.

ol li {
  font-family: Merriweather, serif;
  /* say which counter you want to increment */
  counter-increment: list-counter; 

For nested lists, you can alter the counter style too:

ol li li::before {
  /* increment the counter at this level, but with alphabetic characters */
  content: counter(list-counter, lower-alpha) ". "; 
ol li li li::before {
  /* increment the counter at this level, but with Roman numerals */
  content: counter(list-counter, lower-roman) ". ";

Numbers, but fancier

Sometimes plain ’ol numbers just won’t do the trick. We want a circle with the number in it. It requires a bit more spacing and finessing, but also not too difficult to accomplish.

A fancier numbered list with a colored background behind the numbers
If we want to get really expressive, we can add a background color and shape to the top level element

There's a bit more styling to do, but the concepts are all the same. Building on what we’ve already done, we add this to style the background of the top level list element and give it a bit more space and finesse.

ol.fancier > li {
  margin-bottom: 1em;

ol.fancier > li::before {
  background-color: #c05522;
  border-radius: 50%;
  content: counter(list-counter);
  color: #ffffff;
  min-width: 1.75em;
  min-height: 1.5em;
  margin-left: -1.5em;
  margin-right: 0.35em;
  margin-top: -0.3em;
  padding: 0.3em 0.1em 0.1em;
  text-align: center;

Numbered boxes

This technique also works equally well with other repeating elements, like ‘article’ elements in grid. This can be a nice visual element when designing ’reasons to do something’ where the numbering is more visual element and less list-signifier. I use that technique on my home page to illustrate reasons why someone might hire me.

Fancy numbers next to a set of content blocks to show reading order
I use the numbers as graphic elements on my home page, as the content doesn’t really need to be in a list

Bonus better bullets

The same kind of approach can be taken with bullet lists, so while we don’t need the counters we can still style unordered lists with alternate characters, colors, and styles. Since we’re using generated content to specify the bullet character, it’s equally possible to specify an image or icon.

Better bullet lists with alternate characters and colors
We can use the same sort of trick and use alternate characters for the dots and boxes (this way the line-heights will line up too)

The code for this style is much simpler, and we follow that with alternate bullet characters for nested lists too.

ul {
  list-style: none;
  /* name the counter */
  counter-reset: list-counter; 
ul li {
  /* say which counter you want to increment */
  counter-increment: list-counter; 
ul li::before {
  color: #c05522;
  display: block;
  float: left;
  margin-left: -1em;
  /* set the character for this level */
  content: "●";

ul li li::before {
  /* set the character for this level */
  content: "▪";

ul li li li::before {
  /* set the character for this level */
  content: "◦";

Accessibility concerns

While there have been some issues with removing the semantics of lists when using ‘list-style: none;’ to remove default styling and replace it with our new elements, it appears that  at least with VoiceOver on the Mac (tested with the Catalina version of the OS), this is behaving as expected, and announcing/enumerating lists properly.



Sign up for the newsletterThis is an excerpt from my email newsletter devoted to web typography tips. Each issue I cover a new topic about typography for the web and digital platforms. Sometimes design focused, sometimes technical, usually a bit of both. I archive all the tips here, and all the examples are available on CodePen, so you’ll be able to quickly try out each tip live in the browser, play with it, and take it to use in your own projects.

Become a Patron!