28

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>
Yaroslav Trach
  • 1,833
  • 2
  • 12
  • 18
Möhre
  • 929
  • 1
  • 6
  • 17
  • What result do you want? att it to the counter? You want something like this http://www.w3schools.com/cssref/tryit.asp?filename=trycss_gen_counter-reset ? – Aamir Afridi May 16 '14 at 15:35
  • The counter should match the text numbers =) – Möhre May 16 '14 at 15:36
  • in that specific case `ol[start="10"] { counter-increment: lis 9; }` will work, but I would like to have a generic way. – Möhre May 16 '14 at 15:48
  • the generic way will be through javascript to retrieve start value and then reuse it to generate CSS rules. CSS cannot do this , it can only print at screen attribute value via content:attr(myattribute). – G-Cyrillus May 16 '14 at 16:05

10 Answers10

18

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>

G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • 3
    @Möhre okay , i see it now. As i advise you, you need javascript to retrieve start value. CSS cannot do reuse it like you tried (it is a shame, if attributes value could be reuse this way, there will be lots of easier way to manage things :) ) – G-Cyrillus May 16 '14 at 16:03
  • ...and there must be already an internal function for the default behaviour. Too bad =/ – Möhre May 16 '14 at 16:29
  • @Möhre Yep, really too bad . A jQuey would do ? http://codepen.io/gc-nomade/pen/mCJsd – G-Cyrillus May 16 '14 at 16:51
  • I need a CSS only solution =/. Due this is not possible at the moment I will generate all possibilities in a seperated stylesheet. I noticed that 100x will waste only ~2KB zipped. But thanks for your idea - think it will help other people. – Möhre May 19 '14 at 08:45
  • @Möhre then for the CSS thing, use a preprocessor to generate the css, so no need to edit dozens of similar rules . see http://codepen.io/gc-nomade/pen/cEafh , click on the eye to see 100 rules generated via Scss – G-Cyrillus May 19 '14 at 09:15
  • happily my IDE can do this for me =) – Möhre May 19 '14 at 11:25
  • Dear god, generating 100 CSS rules is the most upvoted answer. Please don't do that. – zopieux May 23 '16 at 16:38
  • @Zopieux what about tons of javscript library and plugins loaded just for a few features ... crazy world in'it ! :) – G-Cyrillus May 23 '16 at 16:43
  • The demos now 404. – Jacob C. Aug 16 '22 at 13:24
13

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

BRN
  • 151
  • 1
  • 4
  • 1
    I would still drop in the "start" attribute value for progressive enhancement or if a user prints the page. `
      ` This inline style works better than any attribute or even any CSS variable approach.
    – jnowland May 27 '19 at 07:45
  • 2
    You need the start attribute for accessibility so that screen reader users get the correct number. – Daniel Tonon Jan 07 '20 at 04:37
6

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 :(

Daniel Tonon
  • 9,261
  • 5
  • 61
  • 64
5

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;
}
Yaroslav Trach
  • 1,833
  • 2
  • 12
  • 18
  • 1
    This is the answer to my problem/question: https://stackoverflow.com/questions/69218523/typo3-ckeditor-removes-attribute-in-frontend-backend-ok – Mario Wilhelm Sep 17 '21 at 07:52
2

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.

G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • Wow, I love it! Still not the final solution, but the best generic one. With this code you don't need JS or additional style rules. – Möhre Sep 26 '19 at 15:35
1

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;
}
SW4
  • 69,876
  • 20
  • 132
  • 137
  • 2
    9 no? `counter-increment: lis 9;` – j08691 May 16 '14 at 15:37
  • @j08691 - The start of 10 is at the `ol` level, then it increments at `li`, so the first would be 11. If the actual designated start is to be 10, then 9 is a better increment for sure – SW4 May 16 '14 at 15:38
  • @Möhre - Have you tried the alternatives noted above? – SW4 May 16 '14 at 15:47
  • @SW4 nope, it just appeared now, but still I see no real solution because the offset can be anything like "17" – Möhre May 16 '14 at 15:54
0

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.

Nubian
  • 153
  • 6
0

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;
}
Duc Manh Nguyen
  • 768
  • 2
  • 8
  • 13
0

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).

Doug Wollison
  • 401
  • 6
  • 15
0

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>