Reverse Ordered Lists in HTML5

Reverse Ordered Lists in HTML5With all the hype surrounding the new APIs and the fancy parts of CSS3, I had almost forgotten about the new reversed attribute that allows you to write a descending list of numbered items, as opposed to the default ascending list of numbered items.

You can get full details in the specification, but here I’ll summarize what it does and I’ll offer a solution for the fact that there is (from what I can see) no browser support for this attribute.

Summary of the “reversed” Attribute

As mentioned, using the new reversed attribute, you can tell the browser that the numbering for the list items should display in descending order, instead of the default ascending.

At first, this confused me. I was under impression that this attribute would actually physically reverse the contents of the list. But that’s not the case. The items will still appear in the same order as they appear in the markup, but the numbers will begin with the highest. So if you have 10 list items, then the first list item will display with a number 10, and the second with a number 9, and so forth.

The syntax is simple, you just add the reversed attribute to any <ol> element. This attribute is a Boolean attribute, so it doesn’t take any value. If you’re using an XHTML doctype, you would need to do reversed="reversed" to pass validation.

The code (as if you needed an example!) looks like this:

<ol reversed>
	<li>List item one</li>
	<li>List item two</li>
	<li>List item three</li>
	<li>List item four</li>
	<li>List item five</li>
</ol>

The result in the browser would be:

A reversed ordered list

The “start” Attribute

In addition to the reversed attribute, HTML5 also reintroduces the start attribute for ordered lists. I say reintroduces because this attribute was introduced in older versions of HTML but eventually became deprecated in HTML4.

Using this attribute, you can specify at what number you want the list to begin. The value must be an integer, otherwise it will just default to “1″. So, without reversed, if you specify a start of “100″, then each list item will be numbered starting with 100. The result would be as shown below:

An ordered list with the start attribute

If you reverse the list, and specify a start value, then the list will begin with that specified value and will go backwards. Like this:

A list with the start attribute, reversed

Because it’s an older attribute, the start attribute has full support everywhere, so that’s good news.

Browser Support for “reversed”?

This section was removed and updated on March 21, 2013

Browser support is as follows:

  • Latest Chrome
  • Latest Firefox
  • Latest Opera (12.14; didn’t work in 12.20)
  • Latest Safari (6.0.3) on Mac; doesn’t work on Safari PC (5.0.3)

So the only major omission is all versions of IE. With the polyfill option (see below), I think this is not too bad. And just as an FYI, there is an open bug report for <ol reversed> on IE10 (you have to be logged in to Microsoft Connect view that bug).

Fixing it With “value” Attributes

Here’s the interesting thing: Every browser allows you to use the value attribute to change the number of each list item directly. This attribute was deprecated in HTML4 but is valid in HTML5.

Using this attribute, we can do this:

<ol>
	<li value=5>List item one</li>
	<li value=4>List item two</li>
	<li value=3>List item three</li>
	<li value=2>List item four</li>
	<li value=1>List item five</li>
</ol>

But we all know that’s pretty lame — unless you’re doing something funky where you’re adding numbers that have no order or whatever.

But this gave me an idea.

A Polyfill for “reversed”

After starting to write this article, and then realizing there was no support, I decided to write a jQuery polyfill. It didn’t take too long, as it accomplishes a pretty simple task: It looks for the presence of the reversed attribute on an ordered list; then it counts the number of list items in the list; then it adds the value attribute to each list item, with the appropriate integer.

It also takes into consideration the start attribute, so if that’s present, it will start the numbered list at that number and descend.

It would be nice if Modernizr detected support for this. I don’t see anything in their docs but I opened an issue to see if it can be added.

You can view or download the code on GitHub and I’ve put up a jsFiddle with some examples. The GitHub repo uses raw JS, while the jsFiddle uses jQuery.

Feel free to offer suggestions for improvement or bug reports.

Update (Dec. 1/2011): I’ve added feature detection to the script on GitHub, and Modernizr has too, my means of an add-on.
Update (Feb. 14/2012): Remy Sharp has kindly rewritten the polyfill so it doesn’t rely on jQuery. If you want the jQuery version instead, you can grab the code from the fiddle.
Update (Feb. 22/2012): Thanks to Jeffrey Barke who pointed out two problems that are now fixed.

29 Responses

  1. Scott Vivian:

    Good stuff! I never figured out exactly why they deprecated the start attribute, since it’s really part of the content and not a style issue.

    One tiny improvement could be made to the polyfill though. Where you have $(myLists).each() that should be myLists.each() since myLists is already a jQuery object. You end up doing $($('ol[reversed]')).

    • Yep, you’re right. I think strangely the jQuery $() wrapper confuses me sometimes. I’ve corrected that in two places on the GitHub repo. Thanks.

      • Pablo Botta:

        jQuery $() is a function so if you pass jQuery object as argument the function will return a clone of the object pointing to the same DOM.
        You can see that in the spec:

        Cloning jQuery Objects

        When a jQuery object is passed to the $() function, a clone of the object is created. This new jQuery object references the same DOM elements as the initial one.

        Reference: jQuery()

    • Marromaw:

      This one always catches me out too. :)

      • The weird thing is, you could do this:

        
        $($($($($($($('ol[reversed]'))))))).each()
        

        And it would still work, albeit probably with performance drawbacks I assume.

    • JoFlo:

      The only problem with the reversed listing is that only the numbers are reversed. At a practicle level, one would want the accompanying text to also be reversed. For e.g. when listing out changes to a code and you want the list displayed chronologically with the latest change at the top. Hope I’m making sense.

      • Yeah, you’re sort of right. But it’s probably the same thing, all things considered. You can reverse the order of the list items manually, displaying them how you want, which is I think just as maintainable.

        In fact, my first impression of reverse ordered lists was that the contents would be reversed, too, so I didn’t understand what the reversed attribute did at first.

  2. Steven:

    I can see how using pseudo elements such as :first-child could be problematic with reversing, but the idea is great nontheless. Thanks for finding this.

    • stephband:

      Using pseudo selectors such as :first-child should not cause any problems, as the chidren themselves do not change order.

  3. You can do this, by the way, with CSS counters alone: http://jsfiddle.net/nYRTK/

    No JavaScript needed.

  4. Sam Sauter:

    I might not entirely get this, so please feel free to correct me, but: Why not use PHP to accomplish exactly the same without writing a js code to get the HTML markup to work? Plus, by not using HTML5 you don’t have to bother writing hacks and fallbacks for all the clients out there who still don’t get the concept of using modern browsers.
    Don’t get me wrong, personally I’m totally into using modern and responsive coding techniques and respect the effort you make to give us a overview. But it occurs to me that in the daily business with websites it (unfortunately) doesn’t make sense yet. Especially considering your own statement: “no support in any browser”.

    • Well, you don’t need PHP, even if you don’t to use JavaScript. As I explained under the heading “Fixing it…”, you can use the “value” attributes on the list items to change the numeric value of each item.

      Yes, you could do that with PHP, and I suppose you could create a function that accepts an argument as the first value. So, that’s an option, no doubt. But many people don’t have a problem with relying on JS to enhance things, and most screen reader users have JS enabled, so it seems okay to me to do this using JS.

      I’m not saying you’re wrong. If you’re concerned about using JS, then by all means, use PHP. I just think most people are pretty comfortable polyfilling this with JS instead so later it can be easily removed when browsers support it natively, and the markup stays the same.

      • Sam Sauter:

        Thanks for your reply, Louis. I’ll keep this in mind and just wait for an overall browser support. CSS3 and HTML5 better be web standards soon. (:

  5. KJS:

    Very good option, some times i use reversed,thx

  6. WOW, I had no idea about the “value” attribute!

  7. Another feature that will probably never be used.

  8. fbender:

    Just a heads-up: Gecko will support the reversed attribute from Gecko / Firefox 18 on which will go to beta next week.

  9. Timwi:

    Why is there a “start” attribute but no “end” attribute? Why do these obvious things never occur to the designers? If I want a reversed list that always ends at, say, 10 no matter how many elements it has, now I always have to calculate a value for the “start” attribute, and remember to fix it whenever I change the list. Are they deliberately trying to make the web as hard to use as possible? (rant over, I had to get this off my shoulder)

    • I don’t understand what you’re asking for…?

      If you have a list of 15 elements, why would you number them from 10 to 1 but then not have numbers for the rest? If you want it like that, then just remove the last five items. I don’t think that’s a design flaw, I think you’re just approaching it the wrong way.

      Unless I’m not understanding what you’re suggesting…?

    • Oh, I see now what you’re saying…. interesting. So if you want it to always end at “10″, then the “start” number would be dependent on the number of items, thus you’d have to have the list starting at a negative number if there were more than 10, and starting at a number higher than 1 if there were less than 10.

      Well, I guess browsers usually only put in features that are actually practical, otherwise there would be too many features to support. To be honest, I can hardly think of a situation that would require a list to always end with 10. Can you provide a realistic example?

      • Timwi:

        I was thinking of a reversed list that ends in 10, i.e. something like 15, 14, 13, 12, 11, 10.

        You clearly think that “start” and “reversed” are useful, otherwise you wouldn’t have written this blog post. Therefore, just take any realistic case for those and combine them, and you have a realistic case for “end”. Anywhere you need a list to start at any specific number, if that list is reversed, you want it to end at a specific number.

        This is further obviated by the fact that the *default* for a reversed list is to end at 1. You can’t even express the default semantics in attributes! That should have been an obvious alarm bell to the designers…

        • Actually, just because I wrote about it, doesn’t mean I think it’s practical. I found it was interesting, so I hacked around with it a little and wrote that polyfill.

          But I don’t personally have many real-world ideas on how to use any of these. In 99% of cases, lists are just straight lists, with no reversed or start needed. That’s why when you throw “end” into the mix, the use cases decrease even more.

          Not that you’re wrong, I just think it’s less important than something that’s already not very important.

        • fbender:

          I think you can do that with the help of CSS: counter(), content(), some clever selectors etc. Shouldn’t be too difficult.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.