How to start a new list, continuing the numbering from the previous list?
Asked Answered
S

13

67

I'm trying to do something that used to be really easy before the start attribute on ol tags was deprecated. I'd just like to have a pair of ordered lists in my page, but start the numbering of the second list where the first one finished. Something like:

1. do stuff
2. do stuff

Here's a paragraph

3. do stuff

I've seen that the counter-reset and counter-increment CSS properties should be able to achieve this, but I can't get it working. Here's my code so far:

<html>
<head>
  <style type="text/css">
    ol li { counter-increment: mycounter; }
    ol.start { counter-reset: mycounter; }
    ol.continue { counter-reset: mycounter 2; }
  </style>
</head>

<body>
  <ol class="start">
    <li>You can't touch this</li>
    <li>You can't touch this</li>
  </ol>
  <p>STOP! Hammer time.</p>
  <ol class="continue">
    <li>You can't touch this</li>
  </ol>
</body>
</html>

To be honest, even if that worked, it wouldn't be ideal. I don't want to have to specify the number reached by the first list in my ol.continue selector.

What am I doing wrong? What's the minimal HTML/CSS combination required to achieve the desired effect?

Splurge answered 6/1, 2011 at 13:42 Comment(1)
I tried this solution. However, I noticed numbers restarted and then being overlapped with the continued nos. Hence, I used Horst Gutmanns approach which resulted in smooth rendering.Mandiemandingo
S
27

As already said, you need :before and content, but you also need to disable the default list numbering. This is your fixed CSS:

ol.start { 
    counter-reset: mycounter; 
}
ol.start li, ol.continue li {
    list-style: none;
}
ol.start li:before, ol.continue li:before { 
    content: counter(mycounter) ". "; 
    counter-increment: mycounter;
}

You don't need to reset the counter for ol.continue, just continue to use your custom counter. The above code makes sure that the counter is only used for the ol.start and ol.continue lists.

Seto answered 6/1, 2011 at 13:56 Comment(3)
Close, but this breaks the list's hanging indent. I'm sure I can fix that, but I'm off into a meeting now and suspect someone else might get there before me... :)Splurge
@Mal Ross: Yep, I know it breaks the indent, you would have to adjust it. There is no way to just replace the automatic number.Seto
great, but how could I get the text in the paragraph to be vertically aligned? with this the second line of a li is right beneath the number, while with normal li the second line starts below the text of the first lineWershba
T
46

A much easier solution to the OP's problem is the following:

<ol start="X">

Where X is the value of the list you want to continue, so in his sample:

<ol>
  <li>You can't touch this</li>
  <li>You can't touch this</li>
</ol>
<p>STOP! Hammer time.</p>
<ol start="3">
  <li>You can't touch this</li>
</ol>
Tacnaarica answered 8/12, 2017 at 9:48 Comment(1)
It's easy to use, but if I add some <li> to the top of the list, I would have to go through all the start attributes that follow and change the value. In other words, it's not automatic, and off by one's are a major time sink for me.Bedelia
S
27

As already said, you need :before and content, but you also need to disable the default list numbering. This is your fixed CSS:

ol.start { 
    counter-reset: mycounter; 
}
ol.start li, ol.continue li {
    list-style: none;
}
ol.start li:before, ol.continue li:before { 
    content: counter(mycounter) ". "; 
    counter-increment: mycounter;
}

You don't need to reset the counter for ol.continue, just continue to use your custom counter. The above code makes sure that the counter is only used for the ol.start and ol.continue lists.

Seto answered 6/1, 2011 at 13:56 Comment(3)
Close, but this breaks the list's hanging indent. I'm sure I can fix that, but I'm off into a meeting now and suspect someone else might get there before me... :)Splurge
@Mal Ross: Yep, I know it breaks the indent, you would have to adjust it. There is no way to just replace the automatic number.Seto
great, but how could I get the text in the paragraph to be vertically aligned? with this the second line of a li is right beneath the number, while with normal li the second line starts below the text of the first lineWershba
P
8

The start attribute is valid in html5. I would just use that.

http://w3c.github.io/html/grouping-content.html#the-ol-element

Also http://dev.w3.org/html5/spec/Overview.html#the-ol-element States that it is still supported in all browsers. You would have to test to be sure I guess.

some jquery to set the start attribute dynamically if you are into that sort of thing..

  // assuming all your ol's have the class mylist
  $(function(){
    var counter=1;
    $('ol.mylist').each(function(){
      $this = $(this);
      $this.attr('start',counter);
      counter += $(this).find('li').length;
    });
  });
Puffy answered 6/1, 2011 at 13:55 Comment(6)
Thanks for the tip, but wouldn't it restrict this part of my site's content to working in only the more recent versions of various browsers? Also, from my reading of it, it means I have to hard-code the starting number for the follow-on list, which is something I'd prefer to avoid.Splurge
If you have two lists you will either have to hard code the start of the second or use script to change the numbering. What about using jquery to update the start attribute?Puffy
w3.org says start is still supported in all major browsers. Don't know how reliable that is since it also still says it's deprecated.Puffy
Thanks for the extra jQuery option. Were it not for my (current) lack of experience with jQuery, I might adopt that as my solution, but given that it's possible to use the counter attributes in CSS without hard-coding the continuation number, I'm going to go with that. Thanks for your input, though - it'll give others reading this question another good option. :)Splurge
w3schools also notes that it IS supported in html5.Goosefish
This function is peferct. Thanks Lee! Newbs, just change class "mylist" to something relevant to your structure and then add "class="relevantClassName" to each of your <ol>'s.Anyaanyah
M
3

Can you not just nest the paragraph inside the list item before you close it?

  <ol>
    <li>You can't touch this</li>
    <li>You can't touch this
      <p>STOP! Hammer time.</p>
      </li>
    <li>You can't touch this</li>
  </ol>
Mathewmathews answered 12/10, 2019 at 4:18 Comment(1)
I tried that. However, I got error message upon running the W3C validator. It seems that OL can contain LI only, no P tags in between list items or nested in a LI tag, according to the W3C validation message.Blarney
D
2

The Opera DevNet has a nice example for exactly this use-case available here: http://devfiles.myopera.com/articles/501/counters-start-example.html (which is part of their article about counters)

So your code should look somehow like this:

<html>
<head>
  <style type="text/css">
    ol li { counter-increment: mycounter; }
    ol.start { counter-reset: mycounter; }
    ol.continue { /*counter-reset: mycounter 2; */}
    ol li { 
        counter-increment: mycounter;
        list-style-type: none;
    }
    ol li:before { content: counter(mycounter) ". "; }
  </style>
</head>

<body>
  <ol class="start">
    <li>You can't touch this</li>
    <li>You can't touch this</li>
  </ol>
  <p>STOP! Hammer time.</p>
  <ol class="continue">
    <li>You can't touch this</li>
  </ol>
</body>
</html>

But, as Lee mentioned, ol@start seems no longer again deprecated, I'd personally prefer that approach since this is not only a styling but also an issue of semantics in your markup.

Delirious answered 6/1, 2011 at 13:56 Comment(2)
Numbering of subsequent <ol> was not correct due to ol.continue. There is no need to reset the counter in continueMandiemandingo
This works well except when the <ol>s are not siblings, in which case the numbering restarts. The solution is to put counter-reset: mycounter; on a common ancestor element e.g. <body> which will make your named variable available to all its descendants. If you don't won't to pollute your whole document put the rule on the highest common ancestor (in this case still <body>!)Feeley
C
2

A minimalistic solution I found was using ol.continued { counter-reset: none; }. Use class="continued" to comprehensibly indicate that some ol is the continuation of the ol before.

Apparently, that works because the browser does ol { counter-reset: list-item } by default (with the language-defined list-item counter) that makes lists reset and count anew when a new list starts. Overriding this gets us the behavior we want.

<style>
    ol.continued { 
       counter-reset: none;
    }
    /* To prove a point */
    ol ::marker {
        color: grey;
        content: "[" counters(list-item, ".") "] ";
    }
</style>
<ol>
    <li>First step
    <ol>
        <li>One sub-step
        <li>Another sub-step
    </ol>
    <li>Second step
</ol>
<p>Some comment in between.</p>
<ol class="continued">          
    <li>Obvious step after the aforementioned comment
    <li>Last step
    <ol>
        <li>A sub-step
        <li>Last sub-step
    </ol>
</ol>

In contrast to assigning value or start, it naturally allows for extending the previous list, i.e. if you add a <li>Third step or remove <li>Second step, counters for the continued list will behave as expected without change. It is maintainable. It works with nested lists and you can style the ::marker whatever you want. Also, this solution does not require boilerplate to remove ::marker and add ::before to replace it.


Note: As of writing this, the presented solution works on Mozilla Firefox only. (Edit: It works on Firefox 92.1.1 on Android, too.) I do not know if this is a bug in Firefox that should not be relied upon, or if this is standard conforming behavior that can reasonably be expected to be followed by and Chrome, Edge and other browsers in the future. MDN promptly suggests that it is intended, as counter-reset: none “can be used to override a counter-reset defined in a less specific rule”. So use it at your own discretion.

This is a screenshot of how the snippet renders on Mozilla Firefox 92.0.1:

Screenshot of the code snipped above in Firefox 92

Crankshaft answered 27/9, 2021 at 15:14 Comment(4)
As of 2022-07-28, on Edge, it still does not work.Crankshaft
Does not work (as of 15 Nov. 2023)Impropriety
@WD It works for me. When I wrote this, I had the browser mentioned in the message. I just pressed Run code snippet and it still works. My current browser is a Firefox 115.4.0 ESR running on a Windows 10 PC. It also works on my Firefox 119.1.1 running on my Android 13 smartphone. MDN (link in the answer) also says it works on Firefox. My best guess is you used another browser.Crankshaft
Does not seem to work on Edge (forgot that part) as of 30 Nov. 2023. [119.0.2151.72 (Official build) (64-bit) on Windows 11]Impropriety
C
1

A similar thing can be achieved using the li tag's value attribute and non-marked list elements.

https://www.w3schools.com/tags/att_li_value.asp

In this approach the insert text becomes an unmarked list item. This is not idiomatic and would make some list-specific defaults about margins and alignment and what not. However this idiomatically keeps the "sparse" list a single tag. Whether this makes the solution better or worse than actually using TWO lists and simulating single list using the ol tag's start attribute - is up to reader to decide.

  <ol>
    <li>You can't touch this
    <li>You can't touch this
    
    <li style="list-style: none"><b>STOP!</b> Hammer time.
      
    <li value="3">You can't touch this
    <li>This neither
  </ol>

You can also add vertical outlines using <br/> or <p> or CSS, same for any other added visual cues.

Example with CSS:

  <ol>
    <li>You can't touch this
    <li>You can't touch this
    
    <li style="list-style: none; margin-top:10px; margin-bottom: 10px"><b>STOP!</b> Hammer time.
      
    <li value="3">You can't touch this
    <li>This neither
  </ol>

Example with HTML tags:

  <ol>
    <li>You can't touch this
    <li>You can't touch this
    
    <li style="list-style: none"><hr/><b>STOP!</b> Hammer time.<hr/>
      
    <li value="3">You can't touch this
    <li>This neither
  </ol>
Croy answered 28/4, 2021 at 13:6 Comment(1)
YES! After endless messing around with counter-set, counter-reset, li:before content etc., someone finally tells me that value exists. Thanks! (I wonder if, as it appears, this is not hooked into the rest of the counter system in any way. I mean why can't I refer to the default counter in CSS?)Drake
V
1

I use a mix of all the answers:

body { 
  counter-reset: cant-touch-this-counter; 
}
ol li { 
  counter-increment: cant-touch-this-counter;
}
ol ::marker {
  content: counter(cant-touch-this-counter) ". ";
}
<ol>
  <li>You can't touch this</li>
  <li>You can't touch this</li>
</ol>
<p>STOP! Hammer time.</p>
<ol>
  <li>You can't touch this</li>
</ol>
Vitalism answered 30/5, 2023 at 9:43 Comment(0)
B
0

Here is an different version of the answer that the OP devised. It makes the text line up if you have more than 9 list items. The pattern could be extended to more than 99 items, more than 999 items, etc.

ol.split { list-style-type: none; }
ol.split li.less-than-ten:before {
    counter-increment: mycounter;
    content: counter(mycounter) ".\00A0\00A0\00A0\00A0";
}

ol.split li.ten-or-greater:before {
    counter-increment: mycounter;
    content: counter(mycounter) ".\00A0\00A0";
}
ol.split li {
    display: list-item;
    text-indent: -2em;
}

ol.start { counter-reset: mycounter; }

To use this put the classes "start" and "split" on the first ol. Put the class "split" on subsequent ol's that you want to include in the continuous numbering. On the 1st through the 9th li tags, put the class "less-than-ten". On the 10th through 99th li tags, put the class "ten-or-greater". If you want to apply the pattern to the 100th through 999th li tags, you will have to create something like this:

ol.split li.more-than-99:before {
    counter-increment: mycounter;
    content: counter(mycounter) ".\00A0\00A0\00A0\00A0\00A0\00A0";
}

I believe the 6 "\00A0" tags will be enough. You may have to fiddle with the number of "\00A0" tags and the text-indent number to make all the text line up.

Briton answered 5/1, 2017 at 14:50 Comment(0)
G
0

There is another approach that I've stumbled across when trying to answer my own question (Remove indent for element within an ordered list <ol>).

I should note that the discussion here helped me answer my question there, although they are different questions they have similar answers; so, thank you to those contributing to the discussion on this thread for your help.

My solution, instead of attributing classes to the list parts of the HTML, attributes a class to the element which is breaking the <ol> elements in two. I used the class name mid-ol. The combination of ol + .mid-ol + ol can then be used in the CSS.

To me this was more satisfactory than changing the character of the <ol> elements, as the list may exist and persist despite the breaking element. For example, the breaking element might be moved, removed, etc., but there's then little maintenance required for the <ol>.

To not duplicate discussion in two places, I'll let anyone interested peruse the discussion and example code on the other thread.

Guitarfish answered 15/6, 2018 at 12:44 Comment(0)
L
0

Today you can use the native start attribute - check it here https://www.w3schools.com/tags/att_ol_start.asp

<ol class="start" start="1">
    <li>You can't touch this</li>
    <li>You can't touch this</li>
  </ol>
  <p>STOP! Hammer time.</p>
  <ol class="continue" start="3">
    <li>You can't touch this</li>
  </ol> 
Latton answered 11/3, 2021 at 9:14 Comment(1)
This appears to just repeat Morkatog's answer from 2017.Cretonne
C
0

Instead of resetting the counter, here is a pure CSS way to achieve what you wanted:

ol {
    padding: 0;
}

li {
    margin-left: 24px;
}

You can then add other elements in the ordered list. These elements will not be indented because the ol padding is set to 0. The list items are still indented because of the margin-left setting of the li. The value of the margin-left of li should match with the default value of the padding of the ol.

Coxalgia answered 13/6, 2022 at 3:45 Comment(0)
F
-1

you also need to use a :before rule with a content tag that references the counter:

see here: http://www.w3schools.com/css/pr_gen_counter-reset.asp

Far answered 6/1, 2011 at 13:47 Comment(2)
This answer would be even better if you fixed the code snippet from the question.Metallic
You are right but i really think people should work a little on their problems today in order to be able to avoid them in the future. I will try to nudge someone in the right direction if i can thou.Far

© 2022 - 2024 — McMap. All rights reserved.