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.
-
2I'd suggest to compare the accepted answer with that by Jakub Jirutka. I think the latter is even much better. – Frank Conijn - Support Ukraine Jul 12 '18 at 16:17
-
Elegant solution. Any idea why Wikipedia uses a ul for its content sections instead of this? – Mattypants Jul 15 '18 at 22:21
-
1@davnicwil I agree; looks like I probably just applied the duplicate in the wrong order back in September. – TylerH Jul 03 '19 at 14:02
-
Cool, now I feel awkward as it never occurred to me it could be a simple error like that - apologies! – davnicwil Jul 03 '19 at 17:06
13 Answers
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.
-
2
-
1@Jason McCreary: Well, that’s the down side: [Counters are not supported in IE until version 8](http://www.quirksmode.org/css/contents.html#t21). – Gumbo Nov 05 '10 at 13:45
-
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
- object so some design can be corrupted by this, also you have to set OL{list-style:none}
– ncubica Aug 18 '11 at 20:00 -
3This 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, ".")". ";` – Mr. Lance E Sloan Jan 20 '14 at 14:09
-
4This is a poor answer. It doesn't work properly. Check out the answer by Jakub Jirutka below – Mr Pablo Oct 28 '14 at 17:26
-
@MrPablo The question is about numbering and not about fixing indentation. – Gumbo Oct 28 '14 at 18:23
-
1@Gumbo I know, and the answer by Jakub gave me the correct numbering. – Mr Pablo Oct 29 '14 at 10:52
-
-
-
SASS VERSION: ol { counter-reset: item; li { display: block; &:before { content: counters(item, ".") " "; counter-increment: item; } } } – Roy van Wensen Nov 29 '17 at 14:07
-
what if a want the list has a start numer? Like a list starting in 3: 3, 3.1, 3.2, 4, 4.1 ... - – Sebastián Rojas Mar 30 '21 at 22:20
-
Still valid in 2023. Came here because ChatGPT wouldn't give me a solution after many prompt iterations. – Yisus Jul 25 '23 at 16:17
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, ".") " ";
}

- 4,644
- 3
- 23
- 37

- 10,269
- 4
- 42
- 35
-
2Good 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](http://jsfiddle.net/p3rtLw7q/23/) and [case 2](http://jsfiddle.net/3J4Bu/199/) -- 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](http://jsfiddle.net/czdf9ykt/) both use case 2 indentation. I guess they are also doing it wrong? – slightlyfaulty Jan 29 '15 at 23:40
-
5It 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. – Jakub Jirutka Jan 30 '15 at 01:18
-
5While 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. – DanielM Mar 30 '15 at 16:13
-
1This 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. – tremby Sep 05 '16 at 02:45
-
2@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](http://jsfiddle.net/rg0b5pqn/4/) for a full example. As an extra bonus I added "text-align: right" to "li:before" to make the numbers right aligned. – mmlr Dec 14 '17 at 12:28
-
@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? – user9437856 Jan 19 '19 at 13:37
-
4Great solution. I added `white-space: nowrap;` to the `ol > li:before` to prevent the numbers from wrapping – Maxim May 16 '21 at 15:38
-
-
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 `
- ` I still get a starting number of 1.
-
Answer of the year! Thank you so much for clearly stating the problem and providing an amazing solution. – user4504661 Aug 17 '23 at 06:31
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/

- 4,644
- 3
- 23
- 37

- 1,401
- 14
- 13
-
1
-
4@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. – slightlyfaulty Aug 12 '14 at 18:20
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:
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
-
This solution looks good after 9 li items coz other solutions had some spacing issue with 2 digit numbers. Thanks – Lahiru Pinto Dec 10 '21 at 14:44
-
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. – crdunst Jul 18 '22 at 11:17
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>

- 510,854
- 105
- 1,084
- 1,005
-
-
@LS You can always accommodate the selectors to suit your need. `.foo > ol > li`. – kennytm Jan 20 '14 at 14:21
-
2My 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. – Mr. Lance E Sloan Jan 20 '14 at 21:07
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.

- 1,984
- 1
- 19
- 25
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

- 4,644
- 3
- 23
- 37

- 165
- 2
- 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>

- 4,274
- 5
- 32
- 43

- 2,140
- 25
- 23
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/

- 71
- 4
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>

- 2,418
- 25
- 27
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;
}

- 4,644
- 3
- 23
- 37

- 63
- 1
- 3
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.

- 4,640
- 6
- 46
- 64
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>

- 4,251
- 10
- 47
- 78