CodeinWP CodeinWP

Reverse Ordered Lists in HTML5

Reverse Ordered Lists in HTML5With all the hype surrounding the new APIs and the fancy parts of CSS, 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, 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.

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 was 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.

Fixing Old Browsers With “value” Attributes

All modern browsers and in-use browsers now support this feature. But if you need older browser support, 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” for Old IE

After starting to write this article, and then realizing there was no support, I decided to write a 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.

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.

32 Responses

  1. Scott Vivian says:

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

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

      This one always catches me out too. :)

    • JoFlo says:

      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.

      • Donald Russell says:

        I disagree that the text order should be reversed too. The text items should be in the order they are written, and only the numbering reversed, as it is. Consider a “Top 10 list, counting down to number 1”:

        
        <ol reversed>
        <li>The most lame reason
        ...
        <li>And the number one reason .... 
        </ol>
        
        
  2. Steven says:

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

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

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

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

    Very good option, some times i use reversed,thx

  6. Ahmad Alfy says:

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

  7. AntoxaGray says:

    Another feature that will probably never be used.

  8. fbender says:

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

  9. Timwi says:

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

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

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

  10. Yst Dawson says:

    Thank you very much for this workaround! My friend uses the text-based Web-browser Links, which both has an issue with ordered lists that start from zero and reversed ordered lists. I really needed a fix for this. Using the “value” attribute on the <li/> tags instead of the “start” attribute on the <ol/> tags causes Links to render the correct numbers.

  11. Mop says:

    “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.”

    You’re wrong about “numbers that have no order or whatever” being “funky”: Crosswords have such lists! I.e.:

    ACROSS
    1. American president.
    3. Opposite of black.

    DOWN
    2. Dwarfs in fairy tales collect this metal.
    3. Romantic flower.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).