92

I was wondering if there is a way to change the color on the bullets in a list.

I have a list like this:

<ul>
   <li>House</li>
   <li>Car</li>
   <li>Garden</li>
</ul>

It is not possible for me to insert anything in the li's such as a 'span' og a 'p'. So can I change the color of the bullets but not the text in some smart way?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Kim Andersen
  • 1,913
  • 4
  • 23
  • 36

13 Answers13

190

I managed this without adding markup, but instead using li:before. This obviously has all the limitations of :before (no old IE support), but it seems to work with IE8, Firefox and Chrome after some very limited testing. The bullet style is also limited by what's in unicode.

li {
  list-style: none;
}
li:before {
  /* For a round bullet */
  content: '\2022';
  /* For a square bullet */
  /*content:'\25A0';*/
  display: block;
  position: relative;
  max-width: 0;
  max-height: 0;
  left: -10px;
  top: 0;
  color: green;
  font-size: 20px;
}
<ul>
  <li>foo</li>
  <li>bar</li>
</ul>
misterManSam
  • 24,303
  • 11
  • 69
  • 89
Marc
  • 3,243
  • 3
  • 23
  • 26
  • 5
    Also, here's how you might do the same thing for ordered lists: http://jsfiddle.net/uZRGN/ – Nightfirecat Sep 09 '11 at 19:28
  • 3
    Excellent. With such wide IE8+ usage I think this should be the answer now. (Note I used `font-size:1em` to get a better-proportioned bullet!) – EvilDr Jul 03 '14 at 11:25
  • I dislike this approach, because what happens when someone tries to render a ul with list-style-type set to none? It means you have to scope these styles under some class, e.g. ul.greenDisc – ctb Aug 01 '17 at 22:46
34

If you can use an image then you can do this. And without an image you won't be able to change the color of the bullets only and not the text.

Using an image

li { list-style-image: url(images/yourimage.jpg); }

See

list-style-image

Without using an image

Then you have to edit the HTML markup and include a span inside the list and color the li and span with different colors.

rahul
  • 184,426
  • 49
  • 232
  • 263
  • 1
    Jep this could work. But actually I decided to use a background-image, and then a list-style-type: none; This gave me the freedom to position the "bullets" a little more than the list-style-image. But still you get the 1+ and right answer. – Kim Andersen Sep 24 '09 at 07:50
  • 6
    Works with data-uri svgs as well: `list-style-image: url('data:image/svg+xml,'); ` – Jon Surrell Sep 18 '15 at 14:42
  • Using @JonSurrell method I was able to achieve a very pleasant result. It's too bad that it isn't one of the suggested answers. The solution is cross-browser for post IE8 and easily modifiable to create interesting custom shapes. – KoldBane Sep 22 '15 at 15:39
  • @KoldBane see my new answer :) – Jon Surrell Sep 22 '15 at 16:37
  • @DimitryK please take a look at the full answer I've written, and direct any comments there. Works well in FF43. – Jon Surrell Jan 12 '16 at 10:26
20

We can combine list-style-image with svgs, which we can inline in css! This method offers incredible control over the "bullets", which can become anything.

To get a red circle, just use the following css:

ul {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><circle fill="red" cx="5" cy="5" r="2"/></svg>');
}

But this is just the beginning. This allows us to do any crazy thing we want with those bullets. circles or rectangles are easy, but anything you can draw with svg you can stick in there! Check out the bullseye example below:

ul {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><circle fill="red" cx="5" cy="5" r="5"/></svg>');
}
ul ul {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><rect fill="red" x="0" y="0" height="10" width="10"/></svg>');
}
ul ul ul {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><circle fill="red" cx="5" cy="5" r="3"/></svg>');
}
ul ul ul ul {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><rect fill="red" x="2" y="2" height="4" width="4"/></svg>');
}
ul.bulls-eye {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10"><circle fill="red" cx="5" cy="5" r="5"/><circle fill="white" cx="5" cy="5" r="4"/><circle fill="red" cx="5" cy="5" r="2"/></svg>');
}
ul.multi-color {
  list-style-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="15" height="15"><circle fill="blue" cx="6" cy="6" r="6"/><circle fill="pink" cx="6" cy="6" r="4"/><circle fill="green" cx="6" cy="6" r="2"/></svg>');
}
<ul>
  <li>
    Big circles!

    <ul>
      <li>Big rectangles!</li>
      <li>b
        <ul>
          <li>Small circles!</li>
          <li>c
            <ul>
              <li>Small rectangles!</li>
              <li>b</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>b</li>
</ul>

<ul class="bulls-eye">
  <li>Bulls</li>
  <li>eyes.</li>
</ul>

<ul class="multi-color">
  <li>Multi</li>
  <li>color</li>
</ul>

Width/height attributes

Some browsers require width and height attributes to be set on the <svg>, or they display nothing. At time of writing, recent versions of Firefox exhibit this problem. I've set both attributes in the examples.

Encodings

A recent comment reminded me of encodings for the data-uri. This was a pain-point for me recently, and I can share a bit of information I've researched.

The data-uri spec, which references the URI spec, says that the svg should be encoded according to the URI spec. That means all sorts of characters should be encoded, eg < becomes %3C.

Some sources suggest base64 encoding, which should fix encoding issues, however it will unnecessarily increase the size of the SVG, whereas URI encoding will not. I recommend URI encoding.

More info:

browser-support: >ie8

css tricks on svgs

mdn on svgs

Community
  • 1
  • 1
Jon Surrell
  • 9,444
  • 8
  • 48
  • 54
  • 1
    This is the best answer so far, and it even works with presentation converters like Cleaver. – gaborous Apr 28 '16 at 20:55
  • 1
    I really like this approach, because the style won't mess up irregular uses of ul, i.e., when list-style-type is set to none, and also because it doesn't depend on wrapping the content of the li in some other element. However, it's not working for me in IE11 or Edge...? – ctb Aug 01 '17 at 22:45
  • @ctb I haven't tested those browsers specifically, but did you read the encodings caveat? You may not be able to copy/paste the "pretty" `` code, try running it through a uri encoder first. – Jon Surrell Aug 02 '17 at 16:46
  • 1
    @JonSurrell yeah, worked once I encoded the svg code. Thx, this was great. – ctb Aug 08 '17 at 17:15
  • 1
    I like this answer because it also supports relative sizes such as r="1.5em" – plx Nov 02 '17 at 15:52
  • @JonSurrell What part are you supposed to encode exactly? The stuff between the tags? But not the tags themselves or any of their attributes? – Kevin Wheeler Feb 28 '23 at 17:52
  • 1
    @KevinWheeler Everything, the SVG tags, attributes, etc. so `` becomes `%3Csvg%3E%3C%2Fsvg%3E`. – Jon Surrell Feb 28 '23 at 19:39
16

Building off @Marc's solution -- since the bullet character is rendered differently with different fonts and browsers, I used the following css3 technique with border-radius to make a bullet that I have more control over:

li:before {
    content: '';
    background-color: #898989;
    display: inline-block;
    position: relative;
    height: 12px;
    width: 12px;
    border-radius: 6px;
    -webkit-border-radius: 6px;
    -moz-border-radius: 6px;
    -moz-background-clip: padding;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
    margin-right: 4px;
    top: 2px;
}
jessica
  • 3,051
  • 2
  • 30
  • 31
  • 1
    @ddilsaver you're right, I was setting the background color in another rule that was specific to each line item (client wanted a different color on each one). i have updated. – jessica Feb 27 '13 at 16:26
  • 2
    Very nice solution. I would suggest to change the border-radius to 50% to make it a little more flexible in case the height/width change. – Tim Jul 20 '16 at 19:06
12

I know this is a really, really, old question but i was playing around with this and came up with a way i have not seen posted. Give the list a color and then overwrite the text color using ::first-line selector. I'm no expert so maybe there is something wrong with this approach that I'm missing, but it seems to work.

li {
  color: blue;
}

li::first-line {
  color: black;
}
<ul>
  <li>House</li>
  <li>Car</li>
  <li>Garden</li>
</ul>
Christopher Moore
  • 3,071
  • 4
  • 30
  • 46
6

Building off both @Marc and @jessica solutions - This is the solution that I use:

li { 
   position:relative;
}
li:before {
      content:'';
      display: block;
      position: absolute;
      width: 6px;
      height:6px;
      border-radius:6px;
      left: -20px;
      top: .5em;
      background-color: #000;
}

I use em for font sizes so if you set your top value to be .5em it will always be placed to the mid point of your first line of text. I used left:-20px because that is the default position of bullets in browsers: parent padding/2

ddilsaver
  • 990
  • 3
  • 10
  • 19
5

::marker

You can use the ::marker CSS pseudo-element to select the marker box of a list item (i.e. bullets or numbers).

ul li::marker {
  color: red;
}

Note: At the time of posting this answer, this is considered experimental technology and has only been implemented in Firefox and Safari (so far).

daniels
  • 4,961
  • 2
  • 22
  • 11
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
2

I really liked Marc's answer too - I needed a set of different colored ULs and obviously it would be easier just to use a class. Here is what I used for orange, for example:

ul.orange {
    list-style: none;
    padding: 0px;
}
ul.orange > li:before {
    content: '\25CF ';
    font-size: 15px;
    color: #F00;
    margin-right: 10px;
    padding: 0px;
    line-height: 15px;
}

Plus, I found that the hex code I used for "content:" was different than Marc's (that hex circle seemed to sit a bit too high). The one I used seems to sit perfectly in the middle. I also found several other shapes (squares, triangles, circles, etc.) right here

1

For me the best option is to use CSS pseudo elements, so for disc bullet styling it would look like that:

ul {
  list-style-type: none;
}

li {
  position: relative;
}

li:before {
  content: '';
  display: block;
  position: absolute;
  width: 5px; /* adjust to suit your needs */
  height: 5px; /* adjust to suit your needs */
  border-radius: 50%;
  left: -15px; /* adjust to suit your needs */
  top: 0.5em;
  background: #f00; /* adjust to suit your needs */
}
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

Notes:

  • width and height should have equal values to keep pointers rounded
  • you may set border-radius to zero if you want to have square list bullets

For more bullets styles you may use other css shapes https://css-tricks.com/examples/ShapesOfCSS/ (choose this which doesn't require pseudo elements to work, so for example triangles)

jmarceli
  • 19,102
  • 6
  • 69
  • 67
0

Building on @ddilsaver's answer. I wanted to be able to use a sprite for the bullet. This appears to work:

li {
  list-style: none;
  position: relative;
}

li:before {
  content:'';
  display: block;
  position: absolute;
  width: 20px;
  height: 20px;
  left: -30px;
  top: 5px;
  background-image: url(i20.png); 
  background-position: 0px -40px; /* or whatever offset you want */
}
ASGM
  • 11,051
  • 1
  • 32
  • 53
James Whittred
  • 103
  • 1
  • 8
0

I tried this today and typed this:
I needed to display color markers in my lists (both bullets and numbers). I came upon this tip and wrote in in my stylesheet whith mutualization of the properties:

ul,
ol {
  list-style: none;
  padding: 0;
  margin: 0 0 0 15px;
}
ul {}
ol {
  counter-reset: li;
}
li {
  padding-left: 1em; 
}
ul li {}
ul li::before,
ol li::before {
  color: #91be3c;
  display: inline-block;
  width: 1em;
}
ul li::before {
  content: "\25CF";
  margin: 0 0.1em 0 -1.1em;
}
ol li {
  counter-increment: li;
}
ol li::before {
  content: counter(li);
  margin: 0 0 0 -1em;
}

I chose a different character to display a bullet, watching it here. I needed to adjust the margin accoardingly, maybe the values won't apply with the font you chose (the numbers use your webfont).

Mars
  • 13
  • 5
0

Try using this instead:

ul {
  color: red;
}
Malekai
  • 4,765
  • 5
  • 25
  • 60
0

Inline version, works for Outlook Desktop:

<ul style="list-style:square;">
  <li style="color:red;"><span style="color:black;">Lorem.</span></li>
  <li style="color:red;"><span style="color:black;">Lorem.</span></li>
</ul>

JSFiddle.

Daniel Ferreira
  • 103
  • 2
  • 7