I have an ordered list that I have incrementing by 1. What I am trying to do is get it to increment by 1 with a dot after the 1:
1.
2.
3.
4
Within my list I have it working like,
1
1.1
1.2
1.3
2
2.1
2.2
3
3.1
3.2
3.3
So that Is correct I just want the number at the beginning to also have a . at the end.
My current code looks something like this:
ol {
counter-reset: item ;
}
li {
display: block;
}
li:before {
content: counters(item, ".") " ";
counter-increment: item;
float: left;
}
<ol>
<li>
<ol>
</ol>
</li>
</ol>
So it should end up looking like:
1.
1.1
1.2
1.3
2.
2.1
2.2
2.3
3.
3.1
3.2
3.3
Here's a Fiddle of what you want.
All I did was change the CSS so that the ordered-list-items have a period at the end, unless they're deeper than 1 level. Fairly simple.
ol li::before {
content: counters(item, ".") ". ";
counter-increment: item;
}
ol ol li::before {
content: counters(item, ".") " ";
}
No need for extra, unnecessary classes.
Hope this helps
If you want the numbers to have a dot at the end change your css to
li:before {
content: counters(item, ".") ".\00a0 ";
}
\00a0 adds space (" " doesn't worked for me).
Edit: Regarding the discussion: give an extra class to the first level and use above CSS (see Codepen).
http://codepen.io/anon/pen/MKOOjv
There is already a topic solving this issue
Achieving sub numbering on ol items html
Credits to Joey
ol { counter-reset: item }
ol>li { display: block }
ol>li:before { content: counters(item, ".") ". "; counter-increment: item }
<ol>
<li>
Tome 1
<ol>
<li>Chapter 1</li>
<li>Chapter 2</li>
</ol>
</li>
</ol>
ol {
counter-reset: item ;
}
li {
display: block;
}
li:before {
content: counters(item, ".") ".";
counter-increment: item;
float: left;
margin-right:10px;
}
<ol>
<li>Test1
<ol>
<li>Test1.1</li>
<li>Test1.2</li>
<li>Test1.3</li>
</ol>
</li>
<li>Test2</li>
<li>Test3</li>
</ol>
I've amended the snippet above. You simply needed to add a "." in the second part of the "content" attribute. I also stuck a margin in there to make it obvious.
Related
.book-summary ol {
counter-reset: item ;
}
.book-summary ol li {
margin-left:10px;
margin-top:5px;
display:block;
}
.book-summary ol li:before {
content: counters(item, ".") " "; counter-increment: item;
}
<div class="book-summary">
<ol>
<li>Component Location</li>
<li>Special Tools</li>
<li>Specifications
<ol>
<li>General Inforamation</li>
<li>Engine</li>
<li>CVT</li>
</ol>
</li>
<li>Torque Specifications</li>
<li>Troubleshooting</li>
<li>cfs</li>
</ol>
</div>
I want to make a ordered list like a table of contents for a book.
However, there is something wrong with my code that my first level list item only have number("1") not ("1.")
What can I do to have a dot after my first level list item?
If you want to makes the first level contains . and the next level without ., you can use nested selector. Example:
.book-summary ol {
counter-reset: item ;
}
.book-summary ol li {
margin-left:10px;
margin-top:5px;
display:block;
}
.book-summary ol li:before {
content: counters(item, ".") " "; counter-increment: item;
}
.book-summary > ol > li:before {
content: counters(item, ".") ". "; counter-increment: item;
}
<div class="book-summary">
<ol>
<li>Component Location</li>
<li>Special Tools</li>
<li>Specifications
<ol>
<li>General Inforamation</li>
<li>Engine</li>
<li>CVT</li>
</ol>
</li>
<li>Torque Specifications</li>
<li>Troubleshooting</li>
<li>cfs</li>
</ol>
</div>
May I know is it possible to create something like this :
1. Food
1.1 Vege
a. Carrot
i. White Carrot
ii. Red Carrot
1.2 Meat
a. Chicken
b. beef
2. Beverages
I've seen many solution for mixed list with numbers and alphabets, but I can't make something like this which include number,nested number, alphabet, roman characters using simpler css code.
Refer to the solution on jsFiddle for this question, it only able to create nested number, but without alphabet and roman characters.
Below is what I did (to fake the effect) :
.primary {
list-style-type: none;
counter-reset: item;
margin: 0px;
padding: 0px;
}
/* Direct child under ol */
.primary>li {
counter-increment: item;
}
/* Before direct child under ol */
.primary>li:before {
content: counters(item, ".") ". ";
padding-right: 0.6em;
}
.primary>li li {
margin: 0px;
}
/* Before li of second level ol */
.primary>li li:before {
content: counters(item, ".") " ";
}
/* Third level ol */
.pri-inner {
list-style-type: lower-alpha;
padding-left:20px;
}
/* Hide the counter content on third level */
.pri-inner li:before {
content:none;
display:none;
}
/* Fourth level ol */
.pri-inner2{
list-style-type: lower-roman;
padding-left:25px;
}
The sample html code look like this
<ol class="primary">
<li>First
<ol class="primary">
<li>Inside First</li>
<li>
<ol class="pri-inner">
<li>Inside inside
<ol class="pri-inner2">
<li>Maximum inside</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li>Second</li>
</ol>
So, is there any better way to achieve that? Because I have to hide the counter on 3rd level.
counter() accepts a second parameter for the list type, i.e. counter(item, lower-alpha)
So the following CSS could do it, or could be tweaked to use your class names.
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, ".") " ";
}
li li li:before {
content: counter(item, lower-alpha) ". ";
}
li li li li:before {
content: counter(item, lower-roman) ". ";
}
http://jsfiddle.net/eke4afd8/
I use Nested counter to create a html ordered list.
This is my code:
http://jsfiddle.net/Katalhama/YpgfF/
I expect this output
0. zero
0.1 zero.one
1. one
1.1. one.one
1.2. one.two
1.3. one.three
2. two
2.1 two.one
2.2 two.two
2.2.1 two.two.one
2.2.2 two.two.two
3. three
But instead I got this:
0. zero
0.0 zero.one
1. one
1.0 one.one
1.1 one.two
1.2 one.three
2. two
2.0 two.one
2.1 two.two
2.1.0 two.two.one
2.2.1 two.two.two
3. three
I want to start with a 0 index, but i wanna sublists index start at 1. My only thought is using two counters, but i'm not familiar with advanced CSS yet and i don't know howw to manage them :(
Thanks all!
There are 2 problems in your code. The first is very serious. The HTML code is in fact invalid. The ol can only contains li elements as direct children. But you added ol elements as direct children of ol. You have to wrap the ol elements inside the li elements. The second problem is the problem you asked for. To achieve what you want, we can set the counter-reset differently for the outermost ol and others ol:
HTML:
<ol id='list'>
<li>one</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three</li>
<li>four
<ol>
<li>four.one</li>
<li>four.two
<ol>
<li>four.two.one</li>
<li>four.two.two</li>
</ol>
</li>
</ol>
</li>
<li>five</li>
</ol>
CSS:
#list {
counter-reset: item -1;
}
ol {
counter-reset: item;
padding-left: 10px;
}
LI { display: block }
LI:before {
content: counters(item, ".") " ";
counter-increment: item;
}
Demo 1
Without using an id for the outermost ol, you can do something like this:
ol {
counter-reset: item -1;
}
ol ol {
counter-reset: item;
padding-left: 10px;
}
LI { display: block }
LI:before {
content: counters(item, ".") " ";
counter-increment: item;
}
Demo 2
Here is another approach:
ol {
counter-reset: item -1;
}
LI { display: block }
LI:before {
content: counters(item, ".") " ";
counter-increment: item;
}
ol ol li:first-child:before {
counter-increment: item 2;
}
Demo 3
To get the correct numbers for the example on JS Fiddle, change the counter-reset to item 0;
CSS
OL {
counter-reset: item 0;
padding-left: 10p;
}
LI {
display: block
}
LI:before {
content: counters(item, ".") " ";
counter-increment: item;
}
And your OL's need to be inside your LIs, you can't have an OL inside an OL
HTML:
<body>
<ol>
<li>one</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three
<ol>
<li>three.one</li>
<li>three.two
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</li>
</ol>
</li>
<li>four</li>
</ol>
</body>
No no your HTML (in the fiddle) is broken. As you mentioned in the title your <ol>'s should be nested, so that means inside other li's, like this
<ol>
<li>Two
<ol>
<li>Two.one</li>
</ol>
</li>
</ol>
At the moment your ol's are direct children of your other ol's. Ol's may only have li's as children (or script tags). So at the moment you have this.
<ol>
<li>Two</li>
<ol>
<li>Two.one</li>
</ol>
</ol>
When you've changed it to the first codeblock in this answer, you can apply different CSS for nested li's, like this:
ol { counter-reset: item -1 }
ol li ol { counter-reset: item 0 }
Demo here: http://jsfiddle.net/kevinvanlierde/YpgfF/1/
By editing Tyblitz HTML structure..which was not showing proper result.
<body>
<ol>
<li>zero</li>
<li>one
<ol>
<li>one.one</li>
<li>one.two</li>
<li>one.three</li>
</ol>
</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two
<ol>
<li>two.two.one</li>
<li>two.two.two</li>
</ol>
</li>
</ol>
</li>
<li>three</li>
</ol>
</body>
CSS
OL { counter-reset: item -1; padding-left: 10px; }
ol li ol { counter-reset: item 0; }
LI { display: block }
LI:before { content: counters(item, ".") " "; counter-increment: item }
JSFiddel
Quite simply, I want an ordered list to work like this:
1. Foo
2. Bar
3a. Baz
3b. Qux
4. Etc...
Is there any way to easily do something along these lines in HTML?
Given the following mark-up:
<ol>
<li>Foo</li>
<li>
<ol>
<li>bar</li>
<li>baz</li>
</ol>
</li>
<li>Something else...</li>
</ol>
The following CSS almost works:
ol {
counter-reset: topLevel;
}
li {
counter-increment: topLevel;
margin-left: 1em;
}
li::before {
content: counter(topLevel) '. ';
margin-right: 0.3em;
}
ol ol {
counter-reset: secondLevel;
}
ol ol li {
counter-increment: secondLevel;
}
ol ol li::before {
content: counter(topLevel) counter(secondLevel, lower-alpha) '. ';
}
JS Fiddle demo.
The only problem with this, so far, is that it contains the topLevel count against both the inner li elements (as you wanted), but also against the outer li (that contains those inner elements), so...not quite there, yet.
And the above problem resolved! ...in those browsers that support the CSS :not() selector:
ol {
counter-reset: topLevel;
}
li {
counter-increment: topLevel;
margin-left: 1em;
}
li:not(.hasChild)::before {
content: counter(topLevel) '. ';
margin-right: 0.3em;
}
ol ol {
counter-reset: secondLevel;
}
ol ol li {
counter-increment: secondLevel;
}
ol ol li::before,
ol li.hasChild ol li::before {
content: counter(topLevel) counter(secondLevel, lower-alpha) '. ';
}
JS Fiddle demo.
I forgot (originally) to note that for this to work (because CSS doesn't have a parent selector (as yet) I had to add a specific class to those li elements with child ol elements in order to appropriately hide the duplication of the number. In this case I chose the class-name .hasChild (as can be seen in the Fiddle).
Incidentally, a small change to the li:not(.hasChild)::before rules, allows for the right-aligned text:
li:not(.hasChild)::before {
content: counter(topLevel) '. ';
width: 2em;
margin-right: 0.3em;
display: inline-block;
text-align: right;
}
JS Fiddle demo.
It doesn't meet your requirements fully and requires some (annoying) changes to your html, but I think it's about as close as you'll get.
http://jsfiddle.net/qGCUk/30/
<ol>
<li>one</li>
<li class="has_children">
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
</ol>
ol,li{
padding:0;
margin:0;
}
ol { counter-reset: item }
li { display: block; padding-left: 0 }
li:before {
content: counters(item, ".") " ";
counter-increment: item
}
LI.has_children:before {
content: " ";
counter-increment: item
}
This is only numbers, as I don't think you can mix numbers and letters. And since there is no selector to select and li which contains and ol, you have to add a class to any li which has a child ol.
I use nested counters and scope to create an ordered list:
ol {
counter-reset: item;
padding-left: 10px;
}
li {
display: block
}
li:before {
content: counters(item, ".") " ";
counter-increment: item
}
<ol>
<li>one</li>
<li>two</li>
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
<li>three</li>
<ol>
<li>three.one</li>
<li>three.two</li>
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</ol>
<li>four</li>
</ol>
I expect the following outcome:
1. one
2. two
2.1. two.one
2.2. two.two
2.3. two.three
3. three
3.1 three.one
3.2 three.two
3.2.1 three.two.one
3.2.2 three.two.two
4. four
Instead, this is what I see (wrong numbering):
1. one
2. two
2.1. two.one
2.2. two.two
2.3. two.three
2.4 three <!-- this is where it goes wrong, when going back to the parent -->
2.1 three.one
2.2 three.two
2.2.1 three.two.one
2.2.2 three.two.two
2.3 four
I have no clue, does anyone see where it goes wrong?
Here is a JSFiddle: http://jsfiddle.net/qGCUk/2/
Uncheck "normalize CSS" - http://jsfiddle.net/qGCUk/3/
The CSS reset used in that defaults all list margins and paddings to 0
UPDATE http://jsfiddle.net/qGCUk/4/ - you have to include your sub-lists in your main <li>
ol {
counter-reset: item
}
li {
display: block
}
li:before {
content: counters(item, ".") " ";
counter-increment: item
}
<ol>
<li>one</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three
<ol>
<li>three.one</li>
<li>three.two
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</li>
</ol>
</li>
<li>four</li>
</ol>
Use this style to change only the nested lists:
ol {
counter-reset: item;
}
ol > li {
counter-increment: item;
}
ol ol > li {
display: block;
}
ol ol > li:before {
content: counters(item, ".") ". ";
margin-left: -20px;
}
Check this out :
http://jsfiddle.net/PTbGc/
Your issue seems to have been fixed.
What shows up for me (under Chrome and Mac OS X)
1. one
2. two
2.1. two.one
2.2. two.two
2.3. two.three
3. three
3.1 three.one
3.2 three.two
3.2.1 three.two.one
3.2.2 three.two.two
4. four
How I did it
Instead of :
<li>Item 1</li>
<li>Item 2</li>
<ol>
<li>Subitem 1</li>
<li>Subitem 2</li>
</ol>
Do :
<li>Item 1</li>
<li>Item 2
<ol>
<li>Subitem 1</li>
<li>Subitem 2</li>
</ol>
</li>
This is a great solution! With a few additional CSS rules you can format it just like an MS Word outline list with a hanging first line indent:
OL {
counter-reset: item;
}
LI {
display: block;
}
LI:before {
content: counters(item, ".") ".";
counter-increment: item;
padding-right:10px;
margin-left:-20px;
}
Keep it Simple!
This is a Simpler and Standard solution to increment the number and to retain the dot at the end.
Even if you get the CSS right, it will not work if your HTML is not correct. see below.
CSS
ol {
counter-reset: item;
}
ol li {
display: block;
}
ol li:before {
content: counters(item, ". ") ". ";
counter-increment: item;
}
SASS
ol {
counter-reset: item;
li {
display: block;
&:before {
content: counters(item, ". ") ". ";
counter-increment: item
}
}
}
HTML Parent Child
If you add the child make sure it is under the parent li.
Will not work ✘
Notice the parent li and the child ol li are individual here, this will not work.
<ol>
<li>Parent 1</li> <!-- Parent has open and close li tags -->
<ol>
<li>Child</li>
</ol>
<li>Parent 2</li>
</ol>
Will work ✔
You need to place the ol li child element inside parent li. Notice the parent li is hugging the child.
<ol>
<li>Parent 1 <!-- Parent open li tag -->
<ol>
<li>Child</li>
</ol>
</li> <!-- Parent close li tag -->
<li>Parent 2</li>
</ol>
After going through other answers I came up with this, just apply class nested-counter-list to root ol tag:
sass code:
ol.nested-counter-list {
counter-reset: item;
li {
display: block;
&::before {
content: counters(item, ".") ". ";
counter-increment: item;
font-weight: bold;
}
}
ol {
counter-reset: item;
& > li {
display: block;
&::before {
content: counters(item, ".") " ";
counter-increment: item;
font-weight: bold;
}
}
}
}
css code:
ol.nested-counter-list {
counter-reset: item;
}
ol.nested-counter-list li {
display: block;
}
ol.nested-counter-list li::before {
content: counters(item, ".") ". ";
counter-increment: item;
font-weight: bold;
}
ol.nested-counter-list ol {
counter-reset: item;
}
ol.nested-counter-list ol > li {
display: block;
}
ol.nested-counter-list ol > li::before {
content: counters(item, ".") " ";
counter-increment: item;
font-weight: bold;
}
ol.nested-counter-list {
counter-reset: item;
}
ol.nested-counter-list li {
display: block;
}
ol.nested-counter-list li::before {
content: counters(item, ".") ". ";
counter-increment: item;
font-weight: bold;
}
ol.nested-counter-list ol {
counter-reset: item;
}
ol.nested-counter-list ol>li {
display: block;
}
ol.nested-counter-list ol>li::before {
content: counters(item, ".") " ";
counter-increment: item;
font-weight: bold;
}
<ol class="nested-counter-list">
<li>one</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three
<ol>
<li>three.one</li>
<li>three.two
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</li>
</ol>
</li>
<li>four</li>
</ol>
And if you need trailing . at the end of the nested list's counters use this:
ol.nested-counter-list {
counter-reset: item;
}
ol.nested-counter-list li {
display: block;
}
ol.nested-counter-list li::before {
content: counters(item, ".") ". ";
counter-increment: item;
font-weight: bold;
}
ol.nested-counter-list ol {
counter-reset: item;
}
<ol class="nested-counter-list">
<li>one</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three
<ol>
<li>three.one</li>
<li>three.two
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</li>
</ol>
</li>
<li>four</li>
</ol>
I think that these answers are over-complicating this. If you don't need to support Internet Explorer, then the solution is a one-liner:
ol > li::marker { content: counters(list-item, '.') '. '; }
<ol>
<li>one</li>
<li>two</li>
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
<li>three</li>
<ol>
<li>three.one</li>
<li>three.two</li>
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</ol>
<li>four</li>
</ol>
See the ::marker CSS pseudo-element page and the Using CSS counters page on MDN's CSS reference website for more information.
I encountered similar problem recently. The fix is to set the display property of the li items in the ordered list to list-item, and not display block, and ensure that the display property of ol is not list-item. i.e
li { display: list-item;}
With this, the html parser sees all li as the list item and assign the appropriate value to it, and sees the ol, as an inline-block or block element based on your settings, and doesn't try to assign any count value to it.
Moshe's solution is great but the problem may still exist if you need to put the list inside a div. (read: CSS counter-reset on nested list)
This style could prevent that issue:
ol > li {
counter-increment: item;
}
ol > li:first-child {
counter-reset: item;
}
ol ol > li {
display: block;
}
ol ol > li:before {
content: counters(item, ".") ". ";
margin-left: -20px;
}
<ol>
<li>list not nested in div</li>
</ol>
<hr>
<div>
<ol>
<li>nested in div</li>
<li>two
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
<li>three
<ol>
<li>three.one</li>
<li>three.two
<ol>
<li>three.two.one</li>
<li>three.two.two</li>
</ol>
</li>
</ol>
</li>
<li>four</li>
</ol>
</div>
You can also set the counter-reset on li:before.
Thank you everyone above for their answers!
As I needed RTL solution, I found out that this can solve it:
ol.nested-counter-list li {
display: block;
unicode-bidi: bidi-override;
}
So you would use any of the solution above, but also update the specific CSS selector for RTL cases.