October 9, 2013

Align Lists Flush Left

It’s surprisingly difficult to left align lists. Most, if not all browsers indent them by default. There are, however, obvious reasons for aligning lists with the surrounding text.

Here are the four options I’ve found for aligning lists:

  1. Set the left margin and padding to zero.
    Text lines up, but bullets and numbers overflow to the left. It isn’t practical for every layout, and on a personal note I find it looks tacky.
  2. Find the left margin value where lists visually align with surrounding text.
    It’s not precise. Each browser has a different bullet size, and number length is variable.
  3. Set bullets inside, add a left margin and use a negative indent to pull the first line back.
    This works really well for bulleted lists, but not for numbered lists. A List Apart shows an example in the article Taming Lists.
  4. Add bullets and numbers in a pseudo element displayed as a table-cell.
    Lately I’ve been working with HTML and CSS tables which inspired this technique, or maybe it’s simply a hack. Regardless, it seems to work well and scales nicely with em units. Keep reading to learn how it works…

Left Align Bulleted Lists

The basic idea is to wrap each bullet in a table-cell using a pseudo element. Support is good across browsers including IE8+.

ul
  display: table
  margin-left: 0
  padding-left: 0
  list-style: none

li
  display: table-row

  &:before
    content: "•"
    display: table-cell
    padding-right: 0.4em

If you use lists for navigation or whatnot, then I recommend replacing ul above with a class to avoid resetting  CSS for other lists.

Left Align Numbered Lists

Ordered lists are tricky because the width changes depending on how many digits are present. The default UA padding is pixel based in most browsers, so long numbers will eventually overflow.

The example below will left align numbers with surrounding paragraph text, and allows for any number length. This works because cells in a column inherit the largest cell width. So, the longest number will determine the column width.

ol
  display: table
  margin-left: 0
  padding-left: 0
  list-style: none

  li
    display: table-row
    counter-increment: table-ol

    &:before
      content: counter(table-ol) "."
      display: table-cell
      padding-right: 0.4em
      text-align: right

I use text-align:right because I like the numbers aligned on their right side when double or triple digits are introduced. If you prefer the numbers be flush regardless of how many digits, you can remove text-align:right.

I typically add margin below list items to separate things a bit, but margin can’t be applied to table rows and cells. In the demo below I define the margin for each li using :after.

See the Pen JszCB by Jeremy Church (@jeremychurch) on CodePen

This comparison shows a list with no styling on the left, and the pseudo table-cell on the right. View the Sass and grab the code, or checkout the full page demo.

View Demo

Final Thoughts

I’m not sure if I’d call this a technique, a trick or a hack, but interesting nonetheless and works quite nicely for aligning numbered lists. And while it works for bullets too, I might recommend the negative indent trick for unordered lists.