Stylish, and accessible, ordered lists with LESS CSS

The design process for most front end designers has evolved over the last few years to remove Photoshop from the workflow, to one where the design goes from wireframe to browser as soon as possible. It allows us to work faster and present a design concept that can be viewed on multiple screens and devices right off the bat.

The basic design concept for the login and signup pages for the MAGICapp project called for a numbered list of the benefits of creating a new account. In years past I might have used icons or images crafted in Photoshop to achieve the desired look, but with what can be achieved in CSS, it's possible to be able to create the design in code that renders well on all screens and devices. Here is a screenshot from the Balsamiq wireframe that shows the basic list design:

Obviously this should be coded as an ordered list. It's semantically correct to do so and it's also nice that it can still be accessible to screen readers. Basically, when the CSS is disabled, it should still render as a numbered list. But, the biggest design challenge with styling ordered lists in CSS is figuring out how to target the numbers separately from the text as shown in the wireframe above. Here's the solution I came up with.

Standard html for the list:

  <ol class="numberedList">
      <li>List item number one</li>
      <li>List item number two</li>
      <li>List item number three</li>
      <li>List item number four</li>
  </ol>

And the basic CSS for the list and first list item:

.numberedList ol {
  list-style-type: none;
}

.numberedList li {
  margin-bottom: 1.75em; // this will depend on your design
  padding-left: 45px; // to make room for the numbers
  position: relative; // for positioning certain numbers more precisely
}

.numberedList li:nth-child(1):before { // this is where the styling of the numbers happens.
  content: "1";
  border: 2px solid #007385;
  color: #007385;
  display: inline-block;
  width: 25px;
  height: 25px;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
  margin-right: 15px;
  text-align: center;
  line-height: 25px;
  font-weight: 700;
  font-size: .9em;
  position: absolute;
  top: 0px;
  left: 0px;
}

It seems a little backwards, but to style the numbers required hiding them from the list by using 'list-style: none' in the CSS and then inserting the numbers as content in the :before tag of each list item. Using nth-child, each list item can now be targeted in order. Then, just make as many nth-children as the list calls for. This becomes very redundant listing out the same CSS values over and over for each list item. Using LESS, these common CSS values can be made as a mixin that can be pulled into the main stylesheet when needed.

The first basic mixin we'll need is one for the border radius of the circled number:

.border-radius (@radius) {
  -webkit-border-radius: @radius;
  -moz-border-radius:    @radius;
  border-radius:         @radius;
}

Next, is a mixin for the circled numbers that are displayed in each of the list items. The .border-radius() mixin being used. Having a common element like this as a LESS mixin allows for much easier style changes across the app, making design in code much more practical. These numbers can be styled however you want.

.circleNumbers () {
  border: 2px solid #007385;
  color: #007385;
  display: inline-block;
  width: 25px;
  height: 25px;
  .border-radius(50%);
  margin-right: 15px;
  text-align: center;
  line-height: 25px;
  font-weight: 700;
  font-size: .9em;
  position: absolute;
  top: 0px;
  left: 0px;
}

And lastly a function that can be called from the main LESS stylesheet to generate the CSS for each of the list items.

.generateOrderedList(@n, @i: 1) when (@i =< @n) {
  &:nth-child(@{i}) {
    &:before {
      content: "@{i}";
      .circleNumbers();
    }
  }

  .generateOrderedList(@n, (@i + 1));
}

So, now anytime in the main LESS stylesheet when I want to use this style of ordered list, I just call the function as you can see in the updated example below. This is for a list with 5 items in it.

ol {
    display: inline-block;
    list-style-type: none;

    li {
      margin-bottom: 1.75em;
      padding-left: 45px;
      position: relative;

      .generateOrderedList(5);
    }
}

And here it is all together. I hope this is helpful to others out there.

See the Pen qDuBl by Rob F (@robfracisco) on CodePen.

Get in touch

Let us know about your CSS tips and tricks in the comments or reach out to us with your web development questions or needs.