7

I'm guessing this isn't possible, but wondering if anybody has attempted to produce ordinal numbers (1st, 2nd, 3rd etc) using CSS Counters with any success?

Obviously this would be trivial in JavaScript, but was hoping to find a style-only solution.

shennan
  • 10,798
  • 5
  • 44
  • 79

3 Answers3

6

It will be easy if you have to add th on every number. But in this case you will need to change the 1st, 2nd, 3rd, 21st, 22nd, 23rd, 31st, 32nd, etc...

So you will need to use nth child concept here. Use :nth-child to target the element.

You will also need to use :not selector to not change the 11th, 12th, 13th element

body {
  margin: 0;
  font: 13px Verdana;
}

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

ul li {
  margin-bottom: 5px;
  position: relative;
}

ul li:before {
  counter-increment: item;
  content: counter(item)"th. ";
  color: red;
  font-weight: bold;
}

ul li:nth-child(10n+1):not(:nth-child(11)):before {
  content: counter(item)"st. ";
}

ul li:nth-child(10n+2):not(:nth-child(12)):before {
  content: counter(item)"nd. ";
}

ul li:nth-child(10n+3):not(:nth-child(13)):before {
  content: counter(item)"rd. ";
}
<ul>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
  <li>listItem</li>
</ul>
Bhuwan
  • 16,525
  • 5
  • 34
  • 57
  • @Bhuwan, the secondary nth-child needs to be (100n+11), etc to account for 11, 111, 211, etc. Similarly needs to be applied for the other two styles. I've submitted an edit for the answer. – Eliseo D'Annunzio Aug 12 '20 at 03:42
  • Worth noting: `:nth-child`-based approaches are going to fail miserably if the `start` property is used on the `ol`, or if `value` is used on any of the `li`s. Of course, I don’t believe there is any alternative that *will* work in that situation (though I am looking/trying!), but it would be worth mentioning the limitation. Otherwise this looks great. – KRyan Dec 17 '20 at 02:41
1

Like this?

body {
  counter-reset: section;
}

h3::before {
  counter-increment: section;
  content: counter(section);
}

h3:nth-child(1)::before {
  content: counters(section, "") "st ";
}

h3:nth-child(2)::before {
  content: counters(section, "") "nd ";
}

h3:nth-child(3)::before {
  content: counters(section, "") "rd ";
}

h3:nth-child(n+4)::before {
  content: counters(section, "") "th ";
}
h3:nth-child(10n+1)::before {
  content: counters(section, "") "st "
}
h3:nth-child(10n+2)::before {
  content: counters(section, "") "nd "
}
h3:nth-child(10n+3)::before {
  content: counters(section, "") "rd "
}
h3:nth-child(11)::before {
  content: counters(section, "") "th "
}
h3:nth-child(12)::before {
  content: counters(section, "") "th "
}
h3:nth-child(13)::before {
  content: counters(section, "") "th "
}
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>
doğukan
  • 23,073
  • 13
  • 57
  • 69
  • you can simply explain that you have used nth-child to differentiate between each case. No need to write a detailed explanation since the code is simple, but you can still avoid the *like this?* ;) ... you may also link to the documentation where we can read more about nth-child for example – Temani Afif Mar 05 '19 at 12:27
0

As of Chrome 86 and Firefox 68 you can drop the manual margin/padding by using ::marker

ol.ordinal {
    list-style: none;

    li::marker {
        content: counter(list-item)"th";
        font-variant-numeric: ordinal;
    }

    li:nth-child(10n+1):not(:nth-child(11))::marker {
        content: counter(list-item)"st";
    }

    li:nth-child(10n+2):not(:nth-child(12))::marker {
        content: counter(list-item)"nd";
    }

    li:nth-child(10n+3):not(:nth-child(13))::marker {
        content: counter(list-item)"rd";
    }
}
Camden Narzt
  • 2,271
  • 1
  • 23
  • 42