How can I prefix ordered list item numbers with a static string using CSS?
Asked Answered
V

3

25

I want this HTML:

<ol style="list-style:decimal;">
<li>Apples</li>
<li>Oranges</li>
</ol>

to render like this:

Q1. Apples
Q2. Oranges

Ie, I want to prefix "Q" to each number.

I've tried CSS like this:

ol li::before {
  content: "Q";
}

but that renders like this:

1. QApples
2. QOranges

I've also tried using list-style: numbered inside;, but that just shifts the list to the right with the same results. I can't find any way to reference the numbers in order to style them with CSS. This seems like such a simple, common scenario, yet I can't find any way to accomplish it with straightforward CSS (without CSS counters, JavaScript, etc).

Vesical answered 6/4, 2011 at 14:41 Comment(0)
B
47

The only pure CSS way is with counters:

ol {
    counter-reset: item;
    list-style-type: none;
}

ol li:before {
    content: 'Q' counter(item, decimal) '. ';
    counter-increment: item;
}

You cannot achieve this besides using CSS counters (which were designed specifically for such use cases!) or JavaScript.

By the way, it's decimal, not numbered.

Bowdlerize answered 6/4, 2011 at 14:43 Comment(9)
Thank you, this is probably exactly what I'm looking for and it's relatively simple. I'm not necessarily opposed to using the counter, if it's actually this simple. My only reservation is... what's the browser support like for this?Vesical
@Gaby: Oops, I missed that. Thanks for the upvote though. @Triynko: Well, admittedly IE support is pretty poor... you can test it here jsfiddle.net/BoltClock/9VdB3Bowdlerize
Also, thanks for the correction on using "decimal" rather than "number" (I edited my original post to correct this); however, in this particular case, it actually needs to be "none", since the numbering is coming from the content style. In that sense, this solution dodges the original question, since it's still not doing anything with the numbered list items, although it achieves the desired results. I'm marking this as the answer unless someone discovers some magical "ol:listnumber:before" selector, haha.Vesical
+1. I wouldn't ever believe that this could work, but I tried it and all modern browsers showed the content correctly.Allyn
I had to change list-style-type: decimal; on the ol to be list-style-type: none; in order to not get double numbers.Gouge
Seems to be supported by all browsers for quite a while now, including IE8+: caniuse.com/#feat=css-countersKaohsiung
Is it possible to mix numbering styles using counter(s)? Like if I wanted to have a nested numbering like 5a. 5b. 5c.ii?Chappie
Thanks for the edit, @Wouter. It was rejected but I uh... used my mod powers to approve it. I really should've fixed it when baacke mentioned it like 6 years ago.Bowdlerize
@BoltClock: haha :) ThxShaneka
U
3

There is a, fragile, non-counter method, but it's prone to breaking:

ol {
    list-style-type: decimal;
    margin: 0 0 0 2em;
}

li {
    position: relative;
}

ol li:first-letter {
    color: #f90;
    float: left;
    position: relative;
    margin-left: -2em;
}

JS Fiddle demo.

Umbrian answered 6/4, 2011 at 14:57 Comment(1)
Yeah, I'm trying to avoid unstable/complex/not-well-supported solutions. The counter solution is stable/simple/well-supported. The fragility of this example rests in that it requires the list number prefix to be a particular size (although using a relative unit like EM instead of PX probably helps insulate it against breaking from font-size changes). I had thought of a similar solution using li:before {content}, but using hard-coded offsets won't support variable-length prefix strings. Plus 1 for implementing it anyway!Vesical
Y
3

Given this HTML:

<ol class="q">
  <li>Apples</li>
  <li>Oranges</li>
</ol>

you could (1) use the @counter-style CSS at-rule:

@counter-style q {
  system: extends decimal;
  prefix: "Q";
}

ol.q {
  list-style: q;
}

(See W3C: CSS Counter Styles Level 3: 3.1.7. Building from Existing Counter Styles: the extends system.) or (2) use CSS counters and the ::marker CSS pseudo-element:

ol.q {
  counter-reset: q;
}

ol.q > li {
  counter-increment: q;
}

ol.q > li::marker {
  content: "Q" counter(q) ". ";
}

Either way, you could set the list-style-position CSS property via the list-style CSS shorthand property to the value inside in order to make the rendered HTML appear like that of BoltClock's answer.

HTML edits: I removed style="list-style:decimal;" because I think that's the default for ol elements. I added class="q" so that the styling only applies to specific lists. I indented each li element by two spaces because I prefer that style.

Yousuf answered 7/8, 2021 at 17:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.