Languages

Web Style Sheets CSS tips & tricks

See also the index of all tips.

On this page:

Colored bullets

Ever wanted to make a list with the bullets a different color than the text, like in this example?

We will also assume that you don't want to, or cannot, change the HTML markup. (See the note below.)

Some day, the '::marker' selector may graduate from proposal to standard and you'll be able to simply say '::marker {color: red}'. But for now you can simulate the effect by combining a handful of properties.

You can make an image and use that: 'list-style: url(mybullet.png)'. That gives you full control over the color and shape of the bullet. But if you want a bigger or smaller font size, you'd have to make a new image. Ditto if you want a different color.

So we'd rather use text that we can style, in particular a bullet such as • or ◦ or ▪. We need to replace the list item's marker, which we cannot select, by a bullet that we generate and style ourselves. For that we suppress the list style and use '::before' to add our own bullet. First suppress the list style:

ul {list-style: none}

Then generate our own bullet:

li::before {content: "•"; color: red}

That inserts a red bullet, but not in the same place as the original bullet. We need to move it to the left, but without moving the text of the list item after it. One way to do that is to make our bullet into an 'inline-block' of a given size, say 1em, and then move it to the left by its own size:

li::before {content: "•"; color: red;
  display: inline-block; width: 1em;
  margin-left: -1em}

That's it.

B.t.w., if you have trouble typing those bullets into your style sheets, you can also use their Unicode numbers: • = "\2022", ◦ = \25E6" and ▪ = "\25AA"

Colored list numbers

What about numbered lists? The idea is the same: we have to replace the automatic counter that we cannot style by one that we generate ourselves. Apart from the properties above, we also need to create a counter. Say we use a counter called 'li'. We first set it to zero on the OL element:

ol {list-style: none; counter-reset: li}

And then we use it like we did the bullet above:

li::before {content: counter(li); color: red;
  display: inline-block; width: 1em;
  margin-left: -1em}

One more thing is missing: As it is our own counter, we're responsible for augmenting it as well:

li {counter-increment: li}

The result looks like this:

  1. First item
  2. Second item

That may be enough, but if you have more than nine items, it looks like this:

  1. First item
  2. Second item
  3. Third item
  4. Fourth item
  5. Fifth item
  6. Sixth item
  7. Seventh item
  8. Eighth item
  9. Ninth item
  10. Tenth item

while you'd probably prefer this:

  1. First item
  2. Second item
  3. Third item
  4. Fourth item
  5. Fifth item
  6. Sixth item
  7. Seventh item
  8. Eighth item
  9. Ninth item
  10. Tenth item

That requires four changes: moving the numbers a bit further to the left and adding that extra amount as margin on the right, right-aligning the list numbers, and setting the direction of the text to 'rtl'. Why the 'rtl'? I'll explain below.

  .example ol li::before {content: counter(li); color: red;
    display: inline-block; width: 1em; margin-left: -1.5em;
    margin-right: 0.5em; text-align: right; direction: rtl}

We put the numbers in a box that is 1em wide and align them to the right. But if the numbers are wider than the box, they will not be right aligned, but left aligned. Text is not allowed to overflow a box on the left side in CSS… unless it is text in a right-to-left language, such as a Hebrew or Arabic. The numbers aren't Hebrew or Arabic letters and so they don't actually go right to left, but by saying our box follows the rules for right-to-left text, we allow the numbers to overflow on the left and thus remain correctly aligned on the right.

(If you don’t want to add the ‘direction: rtl’, you can omit it and instead use a larger width and left margin, e.g., ‘width: 2em; margin-left: -2.5em’. That should provide enough space for correctly aligning numbers up to 999.)

Note on changing the markup

The difficulty of changing the style of the list bullet lies in the fact that both the bullet and the text are in the same element (the LI). If we could put them in different elements, the style rules might become simpler.

I recommend trying to style a document without changing it. The document has a structure that reflects its meaning and you don't want to touch that. You may also have multiple styles for the same document. And sometimes the markup is generated by a system over which you have no control.

However, if you do change the markup, one solution is to wrap the text of each list item in an extra element, e.g., a SPAN. If the list item looks like this: <li><span>First item</span></li> then you can make the bullet red and the text black with `li {color: red}' and `li span {color: black}’. Note that it makes the style sheet shorter, but the document longer, especially if there are many list items. See Dave Burton's demo for more on this method.

Bert Bos, style activity lead
Copyright © 1994–2022 W3C® Privacy policy

Created 17 January 2001;
Last updated Thu 10 Feb 2022 05:40:52 AM UTC

Languages

About the translations