I've seen that you can use various types of counters, as described in the accepted answer to this question: CSS Pseudo Element Counters: can you increment an alphabet letter "a", "b", "c", etc instead of a number?
However, is it possible to increment by a float, e.g. 0.5? This would give a list of, say, 3.0, 3.5, 4.0, 4.5, etc.
Here is what I've tried to do, to no avail:
.values li:before {
content: counter(step);
counter-increment: step 0.5;
}
The value after step is not recognized if it's a float (only if integer).
If this is not possible, is there another method I could use to programmatically set the <li> elements as desired?
Thank you.
You can fake it with multiple rules and nth-child etc
ul {
counter-reset: numbers;
list-style-type: none;
}
li:before {
padding-right: 1em;
}
li:nth-of-type(2n+1)::before {
counter-increment: numbers;
}
li:nth-child(odd)::before {
content: counters(numbers, "") ".0";
}
li:nth-child(even)::before {
content: counters(numbers, "") ".5";
}
<ul>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
</ul>
CSS probably isn't the best thing you can use for this. Try using JavaScript:
var children = document.getElementById("values").children;
var value = 1;
for(var i = 0; i < children.length; i++) {
var child = children[i];
child.innerHTML = value + " " + child.innerHTML;
value += 0.5;
}
<ul id="values">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
You can do it without any hacks, CSS supports this feature. You need to add few counters to content value.
ol {
counter-reset: section;
list-style-type: none;
counter-reset: subsection;
counter-increment: section;
}
li::before {
counter-increment: subsection 5;
content: counter(section) "." counter(subsection) " ";
}
<ol>
<li>item</li>
<li>item
<ol>
<li>item</li>
<li>item</li>
<li>item</li>
</ol>
</li>
<li>item</li>
<li>item</li>
</ol>
Related
Problem:
I was looking to replace the browser's default list-style-type with my own custom ::before pseudo-element. I chose this over the ::marker because of some of the styling limitations the ::marker has.
The HTML code I have has "type" attributes that change what kind of character should appear before the li.
HTML code:
<ol type="decimal">
<li>First ordered item</li>
<li>Second ordered item
<ol type="a">
<li>First ordered item</li>
<li>Second ordered item
<ol type="A">
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
</li>
</ol>
</li>
</ol>
CSS:
This is the CSS I made, using the counter to style it:
ol {
/*list-style-type: none*/
counter-reset: li;
}
ol > li:before {
counter-increment: li;
content: counter(li) ". ";
position: relative;
top: auto;
left: auto;
margin-right: 10px;
color: red;
}
ol[type="decimal"] > li:before {
content: counter(li, decimal) ". ";
}
ol[type="a" s] > li:before {
content: counter(li, lower-alpha) ". ";
}
ol[type="A" s] > li:before {
content: counter(li, upper-alpha) ". ";
}
The "s" after type="a" and type="A" means case-sensitive matches. https://caniuse.com/css-case-insensitive
Firefox vs Chrome:
Looking at the rendered, red characters:
Firefox renders these lists correctly, with the first two being numbers, and the second two being lowercase letters and the last two being uppercase letters.
Chrome renders them incorrectly, with everything being numbers.
Is this an issue with my code/browser support, or is this a bug in Google Chrome?
ol {
/*list-style-type: none*/
counter-reset: li;
}
ol > li:before {
counter-increment: li;
content: counter(li) ". ";
position: relative;
top: auto;
left: auto;
margin-right: 10px;
color: red;
}
ol[type="decimal"] > li:before {
content: counter(li, decimal) ". ";
}
ol[type="a" s] > li:before {
content: counter(li, lower-alpha) ". ";
}
ol[type="A" s] > li:before {
content: counter(li, upper-alpha) ". ";
}
<ol type="decimal">
<li>First ordered item</li>
<li>Second ordered item
<ol type="a">
<li>First ordered item</li>
<li>Second ordered item
<ol type="A">
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
</li>
</ol>
</li>
</ol>
Thank you.
According to caniuse Chrome does not support the case sensitive modifier at the moment (Decmber 2022).
The link you gave goes to the case-insensitive modifier, which Chrome does support it seems.
So it's an issue with browser support rather than a bug as such or an issue with your code
Edit: Down-vote message received (I should have made and posted some attempt at solving the problem), lesson learned, so I'd appreciate not being down-voted any more....
A friend asked me to do a simple web page for them and I'm stumped at one thing -- I want to do an ordered list within an ordered list, like this:
1. something
2. something else
3. something different
3a. and a sub thing
3b. and another sub thing
But the sub list has to have custom strings as its 'numbers'. I can figure out to have just letters, but not numbers and letters.
That's it, but after 30 minutes of googling and being perplexed at counter-increment and counter-reset, I'm wondering if there is a simple way to do this?
Any help much appreciated1
You could work with 2 counters, one for letters & one for numbers.
ul{
padding:0;
list-style-type: none;
}
.root {
counter-reset: numbers;
}
.root > li::before {
counter-increment: numbers;
content: counter(numbers) ". ";
}
.root ul {
padding-left: 15px;
counter-reset: letters;
}
.root ul > li::before {
counter-increment: letters;
content: counter(numbers) counter(letters, lower-alpha) ". ";
}
<ul class="root">
<li>item</li>
<li>item</li>
<li>item
<ul>
<li>sub-item</li>
<li>sub-item</li>
<li>sub-item</li>
</ul>
</li>
<li>item</li>
<li>item
<ul>
<li>sub-item</li>
<li>sub-item</li>
<li>sub-item</li>
</ul>
</li>
<li>item</li>
<li>item</li>
<li>item
<ul>
<li>sub-item</li>
<li>sub-item</li>
<li>sub-item</li>
</ul>
</li>
</ul>
With SASS:
ul{
padding:0;
list-style-type: none;
}
.root {
counter-reset: numbers;
> li::before {
counter-increment: numbers;
content: counter(numbers) ". ";
}
ul {
padding-left: 15px;
counter-reset: letters;
> li::before {
counter-increment: letters;
content: counter(numbers) counter(letters, lower-alpha) ". ";
}
}
}
This will do the trick. Note that this is static HTML, you'll have to manually add the number and it is not in any way an automated solution.
<!DOCTYPE html>
<html>
<head>
<style>
body {
counter-reset: letter-counter;
}
ul {
list-style-type: none;
}
li li::before {
counter-increment: letter-counter;
content: "3" counter(letter-counter, lower-alpha) ". ";
}
</style>
</head>
<body>
<ol>
<li>item</li>
<li>item</li>
<li>item
<ul><li>sub-item</li>
<li>sub-item</li>
<li>sub-item</li></ul></li>
</ol>
</body>
</html>
I am using a self-styled, numbered list. How can I read the start-attribute and add it to the counter with CSS?
ol {
list-style-type: none;
/* this does not work like I expected */
counter-reset: lis attr(start, number, 0);
}
li {
counter-increment: lis
}
li:before {
content: counter(lis)". ";
color: red;
}
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol start="10">
<li>Number Ten</li>
<li>Number Eleven</li>
<li>Number Twelve</li>
</ol>
You may just use the attribute start as a filter :
ol[start="10"] {
counter-reset: lis 9;
}
Demo , but this will only apply for this ol attribute. You would need some javaScript in order to retrieve attribute value to apply, generate the correct counter-reset.
<ins data-extra="Use of Scss">
see this : DEMO to generate 100 rules from these lines :
#for $i from 1 through 100 {
.ol[start="#{$i}"] {
counter-reset: lis $i ;
}
}
Then just copy paste the rules generated if Scss is not avalaible on your hosting .
</in>
<ins data-extra="jQueryFix">:
A jQuery solution can be easily set up :
$( "ol" ).each(function() {
var val=1;
if ( $(this).attr("start")){
val = $(this).attr("start");
}
val=val-1;
val= 'lis '+ val;
$(this ).css('counter-increment',val );
});
Notice that : $(this ).css('counter-reset',val ); works too :)
.</ins>
I see that this is an old question, but I'm putting this here because it may come to help someone yet.
You cannot read an attribute in css counter properties.
Instead, you could use inline css with counter-reset to define the starting number for a particular list.
(Yes, I know it is not a best practice to use inline css, but it can and should be used for edge cases like this one)
The first item increments the reset value by 1, so besides providing the counter name, you will need to subtract the number you want the list to start at by 1:
HTML
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<!-- NOTE: List numbering starts at counter-reset + 1 -->
<ol style="counter-reset: lis 9;" start="10">
<li>Number Ten</li>
<li>Number Eleven</li>
<li>Number Twelve</li>
</ol>
CSS
ol {
list-style-type: none;
counter-reset: lis; /* Resets counter to zero unless overridden */
}
li {
counter-increment: lis
}
li:before {
content: counter(lis)". ";
color: red;
}
FIDDLE (http://jsfiddle.net/hcWpp/308/)
[EDIT]: kept start attribute as suggested to address accessibility and progressive enhancement
Just providing a streamlined version of GCyrillus JS solution
$('ol[start]').each(function() {
var val = parseFloat($(this).attr("start")) - 1;
$(this).css('counter-increment','lis '+ val);
});
I wish CSS could read and use numeric values from HTML attributes :(
ol {
list-style-type: none;
counter-reset: lis var(--start-value, 0);
}
li {
counter-increment: lis;
}
li:before {
content: counter(lis)". ";
color: red;
}
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol style="--start-value: 1;">
<li>Number Two</li>
<li>Number Three</li>
<li>Number Four</li>
</ol>
You can use CSS custom properties (variables), see.
For example, use inline styles for list and add custom property --start-value: 1;.
In CSS you can use it like var(--start-value, 0); with fallback value (0). If you skip this custom property, list will start by default.
HTML
<ol style="--start-value: 1;">
<li>Number Two</li>
<li>Number Three</li>
<li>Number Four</li>
</ol>
CSS
ol {
list-style-type: none;
counter-reset: lis var(--start-value, 0);
}
li {
counter-increment: lis;
}
li:before {
content: counter(lis)". ";
color: red;
}
Back on an old question i have forgotten about.
Nowdays there is the CSS custom properties that could be used , even then , it requires to add a style attribute aside your start attribute
Custom properties (sometimes referred to as CSS variables or cascading variables) are entities defined by CSS authors that contain specific values to be reused throughout a document. They are set using custom property notation (e.g., --main-color: black;) and are accessed using the var() function (e.g., color: var(--main-color);).
example (if the code is generated it seems easier to set both value the same for start=x and var(--s:x) to avoid mistake):
ol {
list-style-type: none;
/* this does not work like I expected
counter-reset: lis attr(start, number, 0); */
/* update using the css varaiable from html */
counter-reset: lis calc(var(--s) - 1) ;
/* calc() is used to keep html attributes values coherent */
}
li {
counter-increment: lis
}
li:before {
content: counter(lis)". ";
color: red;
}
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol start="10" style="--s:10"><!-- or set it right away to nine to get rid of calc() in the css rule-->
<li>Number Ten</li>
<li>Number Eleven</li>
<li>Number Twelve</li>
</ol>
<ol start="30" style="--s:30"><!-- or set it right away to twenty nine to get rid of calc() in the css rule -->
<li>Number Thirty</li>
<li>Number Thirty one</li>
<li>Number Thirty two</li>
</ol>
That's far to late to be an answer but could be useful to anyone else from now.
Simply add:
ol:not(:nth-of-type(1)){
counter-increment: lis 10;
}
Demo Fiddle
You cant use attr in counter-reset unfortunately, but you can add rules to alter the increment amount.
Alternative 1
If you are going to have multiple lists, a more resilient version would be:
ol {
list-style-type: none;
/* this does not work like I expected */
counter-reset: lis;
}
ol:not(:first-of-type){
counter-increment: ol
}
li {
counter-increment: lis
}
li:before {
content: counter(lis)". ";
color: red;
}
ol:not(:first-of-type) li:before {
content: counter(ol) counter(lis)". ";
color: red;
}
Alternative 2
If the numerical prefix can be anything, the below will provision for this:
HTML
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol>
<li data-prefix="1">Number Ten</li>
<li data-prefix="1">Number Eleven</li>
<li data-prefix="1">Number Twelve</li>
</ol>
<ol>
<li data-prefix="a">Number Ten</li>
<li data-prefix="b">Number Eleven</li>
<li data-prefix="c">Number Twelve</li>
</ol>
CSS
ol {
list-style-type: none;
counter-reset: lis;
}
li {
counter-increment: lis
}
li:before {
content: attr(data-prefix) counter(lis)". ";
color: red;
}
To support <ol start="10"> even if counter-reset was enabled in Firefox:
$('ol[start]').each(function() {
var val = parseFloat($(this).attr("start"));
$(this).find("li").first().attr("value", val);
});
jQuery script is based on Daniel Tonon's input.
My solution is: add class no-reset. It's worked for me!
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol start="10" class="no-reset">
<li>Number Ten</li>
<li>Number Eleven</li>
<li>Number Twelve</li>
</ol>
CSS
ol {
list-style-type: none;
counter-reset: lis;
}
li:before {
content: counter(lis)". ";
counter-increment:lis;
color: red;
}
ol.no-reset{
counter-reset: none;
}
You're trying to do a list with custom bullets using the natural numbering, correct? There's a built-in counter called list-item you can use, you don't need to define your own counter.
ol {
list-style: none;
}
li::before {
content: counter(list-item) '. ';
}
If you set this programatically though, Chrome and Safari currently don't apply the changes without a repaint (e.g. toggle display:none).
The above code is a life saver. Quick modification: incorporate the attribute [start] into the CSS selector using the calc so that we can discriminate between which list numbers need calculating. Otherwise you have to set a start and a style attribute for every list (following the first instance of using these attributes).
ol {
list-style-type: none;
/* update using the css variable from html */
counter-reset: lis;
}
ol[start] {
/* select using "start" attribute so we only mod this increment */
counter-reset: lis calc(var(--s) - 1);
/* calc() is used to keep html attributes values coherent */
}
li {
counter-increment: lis
}
li:before {
content: counter(lis)". ";
color: red;
}
<ol>
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
<ol start="10" style="--s:10"><!-- or set it right away to nine to get rid of calc() in the css rule-->
<li>Number Ten</li>
<li>Number Eleven</li>
<li>Number Twelve</li>
</ol>
<ol><!-- numbers won't start from end of prior increment -->
<li>Number One</li>
<li>Number Two</li>
<li>Number Three</li>
</ol>
Is it possible to display only decimal numbers and not the whole numbers at the top level of an ordered list outline? For example:
<ol>
<li>Item
<ol>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ol>
</li>
<li>Item
<ol>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ol>
</li>
<li>Item</li>
<li>Item</li>
CSS
ol {
counter-reset: section;
list-style-type: none;
}
li:before {
counter-increment: section;
content: counters(section,".") " ";
}
That would display a list like:
Item
1.1 Item
1.2 Item
1.3 Item
What I would like to achieve is:
Item
1.1 Item
1.2 Item
1.3 Item
Here is a fiddle I've been trying things out with:
http://jsfiddle.net/Py7k8/
ol {
counter-reset: section;
list-style-type: none;
}
li:before {
counter-increment: section;
content: "";
}
li ol li:before {
content: counters(section,".") " ";
}
DEMO
I need a help to get a., b. style inner indent instead of 2.2.1., 2.2.2.. Found the original CSS code from HTML ordered list indent to keep original numbering
My code:
<style>
ol { counter-reset: item }
li { display: block }
li:before { content: counters(item, ".") ". "; counter-increment: item }
</style>
<ol>
<li>One</li>
<li>
Two
<ol>
<li>Two one</li>
<li>
Two two
<ol type="a">
<li>Two two a</li>
<li>Two two b</li>
</ol>
</li>
<li>Two three</li>
</ol>
</li>
<li>Three</li>
</ol>
What I'm getting:
1. One
2. Two
2.1. Two one
2.2. Two two
2.2.1. Two two a
2.2.2. Two two b
2.3. Two three
3. Three
What I need:
1. One
2. Two
2.1. Two one
2.2. Two two
a. Two two a
b. Two two b
2.3. Two three
3. Three
Since you don't need to prepend the inner lists with the section numbering, you can add an additional rule using counter to get the letters:
ol {
counter-reset: item;
}
li {
list-style: none;
}
li:before {
content: counters(item, ".")". ";
counter-increment: item
}
ol ol ol li:before {
content: counter(item, lower-alpha)". ";
}
Details: http://jsfiddle.net/kmAJ6/3/. Should work with your existing HTML.
Your type attribute has no effect because your css replaces the default numbering. One way around this would be to update your css rules to only target the first 2 levels and let the 3rd level use the default numbering. This will then let your type attribute take effect.
http://jsfiddle.net/TbjcV/
.level1,
.level2{
counter-reset: item
}
.level1 > li,
.level2 > li{
display: block
}
.level1 > li:before,
.level2 > li:before{
content: counters(item, ".") ". ";
counter-increment: item
}
<ol class="level1">
<li>One</li>
<li>
Two
<ol class="level2">
<li>Two one</li>
<li>
Two two
<ol type="a" class="level3">
<li type="a">Two two a</li>
<li>Two two b</li>
</ol>
</li>
<li>Two three</li>
</ol>
</li>
<li>Three</li>
</ol>
I got this:
<style>
ol.cnt { counter-reset: item }
ol.cnt > li { display: block }
ol.cnt > li:before { content: counters(item, ".") ". "; counter-increment: item }
</style>
html:
<ol class="cnt">
<li>One</li>
<li>
Two
<ol class="cnt">
<li>Two one</li>
<li>
Two two
<ol type="a">
<li>Two two a</li>
<li>Two two b</li>
</ol>
</li>
<li>Two three</li>
</ol>
</li>
<li>Three</li>
</ol>
a bit messy, but seems to work.