546

Imagine a simple unsorted list with some <li> items. Now, I have defined the bullets to be square shaped via list-style:square; However, if I set the color of the <li> items with color: #F00; then everything becomes red!

While I only want to set the color of the square bullets. Is there an elegant way to define the color of the bullets in CSS...

...without using any sprite images nor span tags!

HTML

<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<ul>

CSS

li{
   list-style:square;
}
Community
  • 1
  • 1
Sam
  • 15,254
  • 25
  • 90
  • 145
  • 3
    I'm not sure if this can be done elegantly (but I'm no CSS expert). If you don't get a "right" answer, you could consider using list-style-image and setting it to an image of a colored bullet. – Brandon Bohrer Mar 15 '11 at 01:57
  • 2
    Is (was) there any reason why not to use a ? For me this seems to be the only elegant and timeless way of doing this. It works perfectly cross browser even the demon child called IE supports it. It also grands a lot of control between the text and bullet like size. – Madmenyo Jan 18 '14 at 09:50

16 Answers16

1070

The most common way to do this is something along these lines:

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

li {
  padding-left: 1em; 
  text-indent: -.7em;
}

li::before {
  content: "• ";
  color: red; /* or whatever color you prefer */
}
<ul>
  <li>Foo</li>
  <li>Bar</li>
  <li>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</li>
</ul>

JSFiddle: http://jsfiddle.net/leaverou/ytH5P/

Will work in all browsers, including IE from version 8 and up.

Nhan
  • 3,595
  • 6
  • 30
  • 38
Lea Verou
  • 23,618
  • 9
  • 46
  • 48
  • 1
    in contrast to the other *`impossible cannot be done`* answers, you have solved this as a *`very sossible`* answer! Clever, creative, short... timelessy ELEGANT! thanks – Sam Mar 15 '11 at 11:46
  • 79
    being a nitwit, I would remove the extra space in `"• "` ==> `"•"` and add this line below it: `padding-right:7px;` bit more controll there :) the rest is awesome and works everywhere. PS what does the `:before` mean/do here? – Sam Mar 15 '11 at 11:50
  • 23
    instead of `"• "` also possible: `content: "4"; font-family:"Webdings";` which will result in a nice `>` or for a nice ■ `content: "■"; font-family:"Arial Black";` – Sam Mar 15 '11 at 12:21
  • 2
    @Sam #1: :) @Sam #2: You're right about the space, I'm just lazy :$ Better set the padding in ems though, otherwise it'll break when font-size changes (either because you changed the CSS or because the end user adjusted it) @Sam #3: I wouldn't trust dingbat fonts in web pages, some browsers used to choke in the past (haven't tried it recently). Better just use the unicode character. – Lea Verou Mar 15 '11 at 15:49
  • 10
    Oh, and as for what `:before` does: It lets you dynamically insert (presentational) content inside an element, **before** its "real" content. More: http://www.w3.org/TR/CSS21/generate.html#before-after-content (I pasted the CSS2 spec to show you it's not even CSS3) – Lea Verou Mar 15 '11 at 15:51
  • 110
    another alternative to `"•"` is `"\002022"` – yitwail Sep 05 '12 at 19:42
  • 3
    use **content: "● "** for the disc as exactly appear in list-style-type:disc – Krish Nov 16 '12 at 07:51
  • 122
    @Sam "font-family:"Webdings";" is a terrible idea; you can't assume every user will have that font installed on their system (I don't, and I'm pretty sure it's not that common, especially on mobile devices). – WhyNotHugo Jan 07 '13 at 05:17
  • 6
    @LeaVerou This solution negates the effect of `list-style-position: outside;`, and multiple-line `li` don't look well . To solve it, simply use `margin-left: -15px; /*or whatever value works for you*/` – Michał Klimczak Jan 25 '13 at 12:16
  • 5
    Hmm, you could set `display: inline-block` and `width: 0.7em` for `li:before` and only have `text-indent: -0.7em` for `li`. That way, the left edge of the text will be precisely aligned even in multi-line list items. – Mansour Jan 26 '13 at 12:12
  • 1
    Also, by adding one of these spaces: http://en.wikipedia.org/wiki/Space_(punctuation)#Spaces_in_Unicode into the li:before content CSS, such as an Em space, you can get an indent between the list icon and the list body. – Sc0ttyD Mar 28 '13 at 13:22
  • 2
    You can also use almost all unicode characters like ★✱✿♥✎✔☞ etc. If the CSS file has the UTF-8 encoding, these characters can be just pasted there, without any escaping. – Ilya Streltsyn Jul 10 '13 at 18:24
  • 6
    Recommend adding "font-weight:bold;" or even better "font-weight:900" to li:before to enlarge the disc in Lea's solution. Also, krish answer looks great if I copy straight from here to Chrome's console. However my html editor does not know "content: "● "" and turns it into question mark (?) – Jonathan Tonge Oct 16 '13 at 12:06
  • 1
    I use something similar to the answer to achieve a `list-style-position: outside` effect. I give the `:after` selector a value of `position: absolute` and `margin-left: -0.8em` (instead of a `padding-right' declaration). – Walter Roman Jan 06 '14 at 18:41
  • This might have been a good answer in 2011 but nowadays this does not work properly cross browser or not at all. – Madmenyo Jan 18 '14 at 09:46
  • 2
    @MennoGouw It's 2014 here, and this solution works perfectly in Chrome. – Carl Smith May 24 '14 at 10:58
  • 1
    @walterroman so it would work perfectly for about 20% of the people. If you are ook with that then use it. – Madmenyo May 28 '14 at 19:51
  • 2
    Just nice to read "including IE". – chrisdillon Jul 08 '14 at 15:06
  • original bullet with   in css: li:before {content: "\25cf\00a0";} for right aligning: li{padding-left: 1em;text-indent: -1em;} tested with all major browsers – gsziszi Oct 14 '14 at 13:37
  • 2
    To enlarge the circle I added the following to `li:before{font-size: 200%;line-height: 50%;vertical-align: sub;}` – Alexander Taubenkorb Oct 30 '14 at 17:37
  • 1
    @MennoGuow What exactly do you mean? I just tested on the latest Firefox, Chrome, and Opera and it works fine... Not sure if you were referring to someone's comment. – aug Mar 25 '15 at 21:48
  • 2
    It's preferable to provide in unicode, as `"\2022"`. Theoretically, it is "\002022", but you can leave out the leading 0s. Also ref: [Placing Unicode character in CSS content value](http://stackoverflow.com/a/10393517/235415) – Ethan Apr 06 '15 at 21:22
  • This solution depends on how the browser renders the dot. If you replace the character by another one, the alignment does not fit anymore: see http://jsfiddle.net/ytH5P/5024/ – basZero May 12 '15 at 11:47
  • If you want text-shadow to simulate outlines, like in my case, you have to add the shadow width to the padding. Also I prefer pixels to em for this special case: http://jsfiddle.net/mj3evc5y/2/ – Hatoru Hansou Jul 25 '15 at 03:11
  • Why doesn't this work in IE??? – Christine Mar 13 '17 at 21:12
  • 1
    Why isn't this a simple css property? So weird. – Arnaldo Capo Oct 04 '17 at 14:01
  • What if I want to preserve numeric index? No way. This is a hack to me. The best solution is the one by Benito (https://stackoverflow.com/a/13590719/214517) , which simply styles `li` then wraps and styles its content separately. – Niki Romagnoli Sep 23 '18 at 10:51
  • I am unable to apply ANY color when using "\2022", this is in the chrome browser. But when I use `● ` is gets colored correctly. Did some spec change? – Sgnl Jun 26 '19 at 23:42
  • I ran with li {text-indent: -.7em;} – JWC May Feb 06 '23 at 16:52
91

browsing sometime ago, found this site, have you tried this alternative?

li{
    list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAE0lEQVQIW2NkYGD4D8RwwEi6AACaVAQBULo4sgAAAABJRU5ErkJggg==");
}

sounds hard, but you can make your own png image/pattern here, then copy/paste your code and customize your bullets =) stills elegant?

EDIT:

following the idea of @lea-verou on the other answer and applying this philosophy of outside sources enhancement I've come to this other solution:

  1. embed in your head the stylesheet of the Webfont icons Library, in this case Font Awesome:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

  1. take a code from FontAwesome cheatsheet (or any other webfont icons).
i.e.:
fa-angle-right [&#xf105;]

and use the last part of f... followed by a number like this, with the font-family too:

li:before {
    content: "\f105";
    font-family: FontAwesome;
    color: red; /* or whatever color you prefer */
    margin-right: 4px;
}

and that's it! now you have custom bullet tips too =)

fiddle

Facundo Colombier
  • 3,487
  • 1
  • 34
  • 40
  • 3
    I needed a solution for ie7 (of course, does not supports the :before selector). – Facundo Colombier Oct 31 '12 at 02:53
  • 3
    So sorry to say that base64 images don't work in IE7 either... otherwise it would be the best solution... – Diego Sep 30 '13 at 16:17
  • 1
    Upvote for *`out of the box`* thinking – Sam Oct 11 '14 at 11:16
  • 5
    Screw IE7. It's a really old browser by now. This solution rocks! Anyway, if you really want to support IE7 you can just copy and paste the Base64 code into a modern browser address bar, then save the image as a PNG file using Ctrl+S (or Cmd+S in Mac) and use the actual PNG file instead of the Base64 encoded string – OMA Mar 13 '15 at 13:30
  • 1
    Patternify is *awesome* – Dunc May 11 '15 at 12:07
  • 1
    So much cleaner than accepted answer. I hate having to do negative indents and margins. Makes maintenance a nightmare. – CPrescott Dec 04 '15 at 17:29
59

I simply solve this problem like this, which should work in all browsers:

ul li {
  color: red
}

ul li span {
  color: blue;
}
<ul>
  <li><span>Foo</span></li>
  <li><span>Bar</span></li>
  <li><span>Bat</span></li>
</ul>
br3t
  • 1,646
  • 2
  • 20
  • 27
mdthh
  • 1,248
  • 1
  • 13
  • 22
59

The current spec of the CSS 3 Lists module does specify the ::marker pseudo-element which would do exactly what you want; FF has been tested to not support ::marker and I doubt that either Safari or Opera has it. IE, of course, does not support it.

So right now, the only way to do this is to use an image with list-style-image.

I guess you could wrap the contents of an li with a span and then you could set the color of each, but that seems a little hackish to me.

aug
  • 11,138
  • 9
  • 72
  • 93
Alex
  • 64,178
  • 48
  • 151
  • 180
50

One way to do it is using li:before with content: "" and styling it as inline-block element.

Here is a working code snippet:

ul {
  list-style-type: none; /* no default bullets */
}

ul li { 
  font-family: Arial;
  font-size: 18px;
}

ul li:before { /* the custom styled bullets */
  background-color: #14CCBB;
  border-radius: 50%;
  content: "";
  display: inline-block;
  margin-right: 10px;
  margin-bottom: 2px;
  height: 10px;
  width: 10px;
}
<ul>
  <li>Swollen joints</li>
  <li>Pain in hands and knees</li>
  <li>Redness around joints</li>
  <li>Constant fatigue</li>
  <li>Morning stiffness in joints</li>
  <li>High fevers</li>
  <li>Rheumatoid nodules, which develop around joints</li>
</ul>
Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
24

Yet, another solution is to use a :before pseudo element with a border-radius: 50%. This will work in all browsers, including IE 8 and up.

Using the em unit allows responsiveness to font size changes. You can test this, by resizing your jsFiddle window.

ul {
    list-style: none;
    line-height: 1em;
    font-size: 3vw;
}

ul li:before {
    content: "";
    line-height: 1em;
    width: .5em;
    height: .5em;
    background-color: red;
    float: left;
    margin: .25em .25em 0;
    border-radius: 50%;
}

jsFiddle

You can even play with the box-shadow to create some nice shadows, something that will not look nice with the content: "• " solution.

Jose Rui Santos
  • 15,009
  • 9
  • 58
  • 71
  • 1
    This worked perfect. I had to adjust the margin to be: `margin: 0.5em 0.25em 0 0`, but otherwise this was perfect – spasticninja May 08 '17 at 20:29
19

I tried this and things got weird for me. (css stopped working after the :after {content: "";} part of this tutorial. I found you can color the bullets by just using color:#ddd; on the li item itself.

Here's an example.

li{
    color:#ff0000;    
    list-style:square;                
}
a {
    text-decoration: none;
    color:#00ff00;
}

a:hover {
    background-color: #ddd;
}
atiquratik
  • 1,296
  • 3
  • 27
  • 34
Benito
  • 199
  • 1
  • 2
17

I use jQuery for this:

jQuery('li').wrapInner('<span class="li_content" />');

& with some CSS:

li { color: red; }
li span.li_content { color: black; }

maybe overkill, but handy if you're coding for a CMS and you don't want to ask your editors to put an extra span in every list-items.

Veerle Verbert
  • 243
  • 2
  • 2
  • 1
    Aside from the jQuery bit this is the most cross-browser and (for me) cross-email-client compatible solution I have found. – lopsided Feb 13 '14 at 16:37
  • 11
    Email compatible jQuery?? – Carl Smith May 24 '14 at 11:00
  • Keep in mind, that if no javascript is available, the base-color will become your fancy bullets color. – yckart Apr 25 '15 at 09:45
  • I styled the list normally and then if the js ran I updated the styling. That prevents the bullet color from being used for the list if js hasn't executed. Like: jQuery('ol').addClass('ol-wrapper').find('li').wrapInner(''); – Eric Goodwin May 16 '16 at 19:54
10

I would recommend giving the LI a background-image and padding-left. The list-style-image attribute is flakey in cross-browser environments, and adding an extra element, such as a span, is unneccessary. So your code would end up looking something like this:

li {
  background:url(../images/bullet.png) 0 0 no-repeat;
  list-style:none;
  padding-left:10px;
}
atiquratik
  • 1,296
  • 3
  • 27
  • 34
Philip Schweiger
  • 2,714
  • 1
  • 18
  • 27
9

The easiest thing you can do is wrap the contents of the <li> in a <span> or equivalent then you can set the color independently.

Alternatively, you could make an image with the bullet color you want and set it with the list-style-image property.

Adam Bryzak
  • 2,608
  • 2
  • 19
  • 7
8

A variation of Lea Verou solution with perfect indentation in multi-line entries could be something like this:

ul{
    list-style: none;
    position: relative;
    padding: 0;
    margin: 0;
}

li{
    padding-left: 1.5em; 
}

li:before {
    position: absolute;
    content: "•";
    color: red;
    left: 0;
}
Community
  • 1
  • 1
David
  • 2,942
  • 33
  • 16
6

I know it's a bit of a late answer for this post, but for reference...

CSS

ul {
    color: red;
}

li {
    color: black;
}

The bullet colour is defined on the ul tag and then we switch the li colour back.

webster76
  • 93
  • 1
  • 1
6

I am adding my solution to this problem.

I don't want to use image and validator will punish you for using negative values in CSS, so I go this way:

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

li          { padding-left:0.75em; position:relative; }

li:before       { content:"•"; color:#e60000; position:absolute; left:0em; }
Kovo
  • 434
  • 4
  • 14
3

Taking Lea's demo, here's a different way of making unordered lists, with borders: http://jsfiddle.net/vX4K8/7/

HTML

<ul>
    <li>Foo</li>
    <li>Bar</li>
    <li>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</li>
        <ul>
        <li>Son</li>
        <li>Of</li>
            <ul>
            <li>Foo</li>
            <li>Bar</li>
            <li>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</li>
            </ul>
        </ul>
</ul>

CSS

ul {
list-style: none;
margin: 0;
}

ul:first-child {
   padding: 0;
}

li {
    line-height: 180%;
    border-bottom: 1px dashed #CCC;
    margin-left: 14px;
    text-indent: -14px;
}

li:last-child {
    border: none;
}

li:before {
    content: "";
    border-left: 4px solid #CCC;
    padding-left: 10px;
}
  • @user2188875 Very interesting twist! Thanks for elevating the question and so creatively adding new meaning to the answer. Indeed this way lists could be stylised very maturely! Is this compatible in email html templates too? say one would use this for html mails and send them. Would the receiving party (mac/win7/win10/android/etc) see and read the html properly?? – Sam Jan 14 '16 at 23:24
3

Lea Verous solution is good but i wanted more control over the position of the bullets so this is my approach:

.entry ul {
    list-style: none;
    padding: 0;
    margin: 0;
    /* hide overflow in the case of floating elements around ... */
    overflow: hidden;
}
.entry li { 
    position: relative;
    padding-left: 24px;
}
.entry li:before {
    /* with absolute position you can move this around or make it bigger without getting unwanted scrollbars */
    position: absolute;
    content: "• ";
    color: #E94E24;
    font-size: 30px;
    left: 0;
    /* use fonts like "arial" or use "sans-serif" to make the dot perfect round */ 
    font-family: Arial, sans-serif;
}
herrfischer
  • 1,768
  • 2
  • 22
  • 35
-17

This will do it..

li{
  color: #fff;
}
Magicprog.fr
  • 4,072
  • 4
  • 26
  • 35