Can ordered list produce result that looks like 1.1, 1.2, 1.3 (instead of just 1, 2, 3, ...) with css?
Asked Answered
H

13

270

Can an ordered list produce results that looks like 1.1, 1.2, 1.3 (instead of just 1, 2, 3, ...) with CSS? So far, using list-style-type:decimal has produced only 1, 2, 3, not 1.1, 1.2., 1.3.

Herc answered 4/11, 2010 at 15:21 Comment(4)
I'd suggest to compare the accepted answer with that by Jakub Jirutka. I think the latter is even much better.Ingredient
Elegant solution. Any idea why Wikipedia uses a ul for its content sections instead of this?Simard
@davnicwil I agree; looks like I probably just applied the duplicate in the wrong order back in September.Foldaway
Cool, now I feel awkward as it never occurred to me it could be a simple error like that - apologies!Hekate
A
360

You can use counters to do so:

The following style sheet numbers nested list items as "1", "1.1", "1.1.1", etc.

OL { counter-reset: item }
LI { display: block }
LI:before { content: counters(item, ".") " "; counter-increment: item }

Example

ol { counter-reset: item }
li{ display: block }
li:before { content: counters(item, ".") " "; counter-increment: item }
<ol>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
  <li>li element</li>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
</ol>

See Nested counters and scope for more information.

Anthracite answered 4/11, 2010 at 15:30 Comment(12)
great answer. What is the support for this?Lynch
@Jason McCreary: Well, that’s the down side: Counters are not supported in IE until version 8.Anthracite
ohhh this is nice... man.. didn't know neither of this possibility. Working in my design now... the only bad thing about this is that the algorithm insert a new DOM object with the number 1.1, 1.2 etc next of the <li>object so some design can be corrupted by this, also you have to set OL{list-style:none}Moisesmoishe
This solution misses one tiny thing: the dot following the item number. It doesn't look like the standard list style. Fix by adding a dot to the rule for li:before: content: counters(item, ".")". ";Central
This is a poor answer. It doesn't work properly. Check out the answer by Jakub Jirutka belowErubescence
@MrPablo The question is about numbering and not about fixing indentation.Anthracite
@Anthracite I know, and the answer by Jakub gave me the correct numbering.Erubescence
This also seems to number un-ordered lists, which is badCry
@Cry Replace LI by UL > LI.Anthracite
SASS VERSION: ol { counter-reset: item; li { display: block; &:before { content: counters(item, ".") " "; counter-increment: item; } } }Devotional
what if a want the list has a start numer? Like a list starting in 3: 3, 3.1, 3.2, 4, 4.1 ... -Neptune
Still valid in 2023. Came here because ChatGPT wouldn't give me a solution after many prompt iterations.Leeann
M
352

None of solutions on this page works correctly and universally for all levels and long (wrapped) paragraphs. It’s really tricky to achieve a consistent indentation due to variable size of marker (1., 1.2, 1.10, 1.10.5, …); it can’t be just “faked,” not even with a precomputed margin/padding for each possible indentation level.

I finally figured out a solution that actually works and doesn’t need any JavaScript.

It’s tested on Firefox 32, Chromium 37, IE 9 and Android Browser. Doesn't work on IE 7 and previous.

CSS:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;    
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") " ";
}

Example: Example

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;
}

li li {
  margin: 0;
}

li li:before {
  content: counters(item, ".") " ";
}
<ol>
  <li>Lorem ipsum.</li>
  <li>Excepteur sint occaecat cupidatat non proident:
    <ol>
      <li>sunt in culpa qui officia,</li>
      <li>deserunt mollit anim id est laborum.</li>
    </ol>
  </li>
  <li>Ut enim ad minim veniam.
    <ol>
      <li>Quis nostrud exercitation.</li>
      <li>Ullamco laboris nisi ut.
        <ol>
          <li>
            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
          </li>
        </ol>
      </li>
    </ol>
  </li>
  <li>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia
    animi.</li>
</ol>

Try it on JSFiddle, fork it on Gist.

Mablemabry answered 7/10, 2014 at 20:50 Comment(10)
Good job achieving this type of indention. I would still argue however that the first 2 cases of indentation that you've listed are a matter of preference rather than right and wrong. Consider case 1 and case 2 -- the latter manages to squeeze in a lot more levels before the spacing becomes unwieldy, while still looking pretty neat. Furthermore, MS Word and default browser styling both use case 2 indentation. I guess they are also doing it wrong?Trapan
It really does work (technically) for all levels and long paragraphs. If it's reasonable to use dozen levels, that's another question that has nothing to do with the technical solution. The point is that you don't have to predefine a CSS rule for each nesting level like with some other solutions.Mablemabry
While I wouldn't say there's anything inherently "wrong" with the other answers, I would say they are incomplete. This answer is spot on, and even worked in a horrifically bizarrely styled site I am amending.Transept
This is great. The one issue is that indentation is not consistent for all items of a long list. For example once you get up to 1.1.10, that item is indented slightly more than 1.1.9 due to the width of the extra digit.Mairemaise
@tremby: The discrepancy can be solved by making the li use "display: table-row" instead of "display: table". The problem this brings is that the li then can't use any margins/paddings as table-rows are always sized automatically by their content. This can be worked around by adding an "li:after" with "display: block". See jsFiddle for a full example. As an extra bonus I added "text-align: right" to "li:before" to make the numbers right aligned.Sunda
@JakubJirutka, Really appreciate your answer. I have one doubt that I am getting, for example, 1->1.1,1.2,1.3 now inside 1.3 have (i),(ii),(iii). how do I display that?Windbag
Great solution. I added white-space: nowrap; to the ol > li:before to prevent the numbers from wrappingTheta
While this looks great for simple lists, it doesn't work with manually setting an item's value or the starting value for a list. If I use <ol start="15"> I still get a starting number of 1.Intellectualize
Answer of the year! Thank you so much for clearly stating the problem and providing an amazing solution.Mighell
even 13 years later this answer still going strong!Outrageous
T
75

The chosen answer is a great start, but it essentially forces list-style-position: inside; styling on the list items, making wrapped text hard to read. Here's a simple workaround that also gives control over the margin between the number and text, and right-aligns the number as per the default behaviour.

ol {
    counter-reset: item;
}
ol li {
    display: block;
    position: relative;
}
ol li:before {
    content: counters(item, ".")".";
    counter-increment: item;
    position: absolute;
    margin-right: 100%;
    right: 10px; /* space between number and text */
}

JSFiddle: http://jsfiddle.net/3J4Bu/

Trapan answered 29/4, 2013 at 2:9 Comment(2)
One downside is it adds a period to the end of each list item.Hargeisa
@Davin Studer: It only adds a period to the end of each number, as per the default ol behaviour. It can easily be removed by deleting the last "." from the content property, but this just looks a bit odd to me.Trapan
G
21

The solutions posted here did not work well for me, so I did a mixture of the ones of this question and the following question: Is it possible to create multi-level ordered list in HTML?

/* Numbered lists like 1, 1.1, 2.2.1... */
ol li {display:block;} /* hide original list counter */
ol > li:first-child {counter-reset: item;} /* reset counter */
ol > li {counter-increment: item; position: relative;} /* increment counter */
ol > li:before {content:counters(item, ".") ". "; position: absolute; margin-right: 100%; right: 10px;} /* print counter */

Result:

screenshot

Note: the screenshot, if you wish to see the source code or whatever is from this post: http://estiloasertivo.blogspot.com.es/2014/08/introduccion-running-lean-y-lean.html

Glaring answered 14/8, 2014 at 1:46 Comment(2)
This solution looks good after 9 li items coz other solutions had some spacing issue with 2 digit numbers. ThanksUngrateful
I initially upvoted, this answer, but then I noticed rendering issues in Chrome. It was intermittent, and seemed to occur further down the list, where the counters weren't resetting for some reason. Would be okay on one view, refresh the numbers would be long without a reset. No idea why. Jakub's answer worked for me.Stucco
A
8

Note: Use CSS counters to create nested numbering in a modern browser. See the accepted answer. The following is for historical interest only.


If the browser supports content and counter,

.foo {
  counter-reset: foo;
}
.foo li {
  list-style-type: none;
}
.foo li::before {
  counter-increment: foo;
  content: "1." counter(foo) " ";
}
<ol class="foo">
  <li>uno</li>
  <li>dos</li>
  <li>tres</li>
  <li>cuatro</li>
</ol>
Abie answered 4/11, 2010 at 15:30 Comment(3)
This solution fails horribly when the lists are nested.Central
@LS You can always accommodate the selectors to suit your need. .foo > ol > li.Abie
My point is that you've hard-coded "1." into the style. What happens when the sublist is a child of the second item in the parent list? You want it to appear as "2.", but it will always be "1." because of the way it's coded here. What's the solution? Make new sets of styles for every possible number? No. Use the counters() function as in the examples above instead of the counter() function.Central
P
6

In the near future you may be able to use the ::marker psuedo-element to achieve the same result as other solutions in just one line of code.

Remember to check the Browser Compatibility Table as this is still an experimental technology. At the moment of writing only Firefox and Firefox for Android, starting from version 68, support this.

Here is a snippet that will render correctly if tried in a compatible browser:

::marker { content: counters(list-item,'.') ':' }
li { padding-left: 0.5em }
<ol>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
  <li>li element</li>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
</ol>

You may also want to check out this great article by smashingmagazine on the topic.

Pimental answered 7/10, 2019 at 11:24 Comment(0)
H
5

The following worked for me:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ") ";
  display: table-cell;
  padding-right: 0.6em;
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") ") ";
}

Look at: http://jsfiddle.net/rLebz84u/2/

or this one http://jsfiddle.net/rLebz84u/3/ with more and justified text

Hurling answered 23/2, 2016 at 1:19 Comment(0)
I
2
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="author" content="Sandro Alvares - KingRider">
    </head>
    <body>
        <style type="text/css">
            li.title { 
                font-size: 20px; 
                font-weight: lighter; 
                padding: 15px; 
                counter-increment: ordem; 
            }
            .foo { 
                counter-reset: foo; 
                padding-left: 15px; 
            }
            .foo li { 
                list-style-type: none; 
            }
            .foo li:before { 
                counter-increment: foo; 
                content: counter(ordem) "." counter(foo) " "; 
            }
        </style>
        <ol>
            <li class="title">TITLE ONE</li>
            <ol class="foo">
                <li>text 1 one</li>
                <li>text 1 two</li>
                <li>text 1 three</li>
                <li>text 1 four</li>
            </ol>
            <li class="title">TITLE TWO</li>
            <ol class="foo">
                <li>text 2 one</li>
                <li>text 2 two</li>
                <li>text 2 three</li>
                <li>text 2 four</li>
            </ol>
            <li class="title">TITLE THREE</li>
            <ol class="foo">
                <li>text 3 one</li>
                <li>text 3 two</li>
                <li>text 3 three</li>
                <li>text 3 four</li>
            </ol>
        </ol>
    </body>
</html>

Result: https://i.stack.imgur.com/78bN8.jpg

Intracellular answered 25/9, 2013 at 12:33 Comment(0)
F
2

I have some problem when there are two lists and second one is inside DIV Second list should start at 1. not 2.1

<ol>
    <li>lorem</li>
    <li>lorem ipsum</li>
</ol>

<div>
    <ol>
        <li>lorem (should be 1.)</li>
        <li>lorem ipsum ( should be 2.)</li>
    </ol>
</div>

http://jsfiddle.net/3J4Bu/364/

EDIT: I solved the problem by this http://jsfiddle.net/hy5f6161/

Foscalina answered 22/12, 2015 at 8:26 Comment(0)
I
1

this is proper code if you want to first child li resize of other css.

<style>
    li.title { 
        font-size: 20px; 

        counter-increment: ordem; 
        color:#0080B0;
    }
    .my_ol_class { 
        counter-reset: my_ol_class; 
        padding-left: 30px !important; 
    }
    .my_ol_class li { 
          display: block;
        position: relative;

    }
    .my_ol_class li:before { 
        counter-increment: my_ol_class; 
        content: counter(ordem) "." counter(my_ol_class) " "; 
        position: absolute;
        margin-right: 100%;
        right: 10px; /* space between number and text */
    }
    li.title ol li{
         font-size: 15px;
         color:#5E5E5E;
    }
</style>

in html file.

        <ol>
            <li class="title"> <p class="page-header list_title">Acceptance of Terms. </p>
                <ol class="my_ol_class">
                    <li> 
                        <p>
                            my text 1.
                        </p>
                    </li>
                    <li>
                        <p>
                            my text 2.
                        </p>
                    </li>
                </ol>
            </li>
        </ol>
Italianize answered 5/9, 2016 at 8:26 Comment(0)
A
0

I needed to add this to the solution posted in 12 as I was using a list with a mixture of ordered list and unordered lists components. content: no-close-quote seems like an odd thing to add I know, but it works...

ol ul li:before {
  content: no-close-quote;
  counter-increment: none;
  display: list-item;
  margin-right: 100%;
  position: absolute;
  right: 10px;
}
Amatory answered 15/8, 2014 at 14:6 Comment(0)
B
0

I was after adding numbered list to Python Markdown's TOC Extension.

I did something like this:

.toc ul { counter-reset: outItem; list-style: none }
.toc ul > li{ counter-reset: nestedItem }
.toc ul > li:before { content: counters(outItem, ".") ". "; counter-increment: outItem; margin-left: -2em; }

I am not sure it is the correct way, but it worked for me.

Bahner answered 22/5, 2021 at 14:4 Comment(0)
T
0

This is a monospace example that emulates an RFC Table of Contents. 5 levels of depth.

/* Table of Contents - Decimal */
.toc-decimal ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
  font-family: monospace;
}
.toc-decimal ol li {
  display: table-row;
  counter-increment: item;
  margin-bottom: 0.6em;
}
.toc-decimal ol li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;    
}
.toc-decimal ol li li {
  margin: 0;
}
.toc-decimal ol li li:before {
  content: counters(item, ".") ". ";
}


/* Table of Contents - Upper Alpha */
.toc-upper-alpha ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
  font-family: monospace;
}
.toc-upper-alpha ol li {
  display: table-row;
  counter-increment: item;
  margin-bottom: 0.6em;
}
.toc-upper-alpha ol li:before {
  content: "A." counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;    
}
.toc-upper-alpha ol li li {
  margin: 0;
}
.toc-upper-alpha ol li li:before {
  content: "A." counters(item, ".") ". ";
}
<!-- Table of Contents - Decimal -->
<section class="toc-decimal">

  <!-- Ordered List -->
  <ol>
    <li>Depth 1
      <ol>
        <li>Depth 2</li>
        <li>Depth 2</li>
        <li>Depth 2
          <ol>
            <li>Depth 3</li>
            <li>Depth 3</li>
            <li>Depth 3
              <ol>
                <li>Depth 4</li>
                <li>Depth 4</li>
                <li>Depth 4
                  <ol>
                    <li>Depth 5</li>
                    <li>Depth 5</li>
                    <li>Depth 5</li>
                  </ol>
                </li>
              </ol>
            </li>
          </ol>
        </li>
      </ol>
    </li>
    <li>Depth 1</li>
  </ol>

</section>

<hr>

<!-- Table of Contents - Upper Alpha -->
<section class="toc-upper-alpha">

  <!-- Ordered List -->
  <ol>
    <li>Depth 1
      <ol>
        <li>Depth 2</li>
        <li>Depth 2</li>
        <li>Depth 2
          <ol>
            <li>Depth 3</li>
            <li>Depth 3</li>
            <li>Depth 3
              <ol>
                <li>Depth 4</li>
                <li>Depth 4</li>
                <li>Depth 4
                  <ol>
                    <li>Depth 5</li>
                    <li>Depth 5</li>
                    <li>Depth 5</li>
                  </ol>
                </li>
              </ol>
            </li>
          </ol>
        </li>
      </ol>
    </li>
    <li>Depth 1</li>
  </ol>

</section>
Trojan answered 15/3, 2023 at 15:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.