How do you add a custom bullet in CSS?

ยท

4 min read

I've lost count of the number of times a designer has come up to me with a shiny new design that has a list with custom markers. This is always a useful thing to know how to do

Previously...

There were a few ways we could tackle this

List Style Properties

  • list-style-type: This will let you set the type of the bullet. E.g. square, circle, numbers, etc. See MDN for full list

    ul {
      list-style-type: square;
    }
    
  • list-style-position: This will let you set the position of the bullet either inside or outside the list-item. This is outside by default

    ul {
      list-style-position: inside; 
    }
    

    Heres how the box model looks set to outside; list-style-position outside box model And set to inside; list-style-position inside box model

  • list-style-image: This will let you set the bullet to any image, similar to background-image

    ul {
      list-style-image: url(customBullet.svg);
    }
    

We can shorthand all of the above to the following:

ul {
  list-style: square url(customBullet.svg) inside;
}

You might be looking at that and wondering 'why the heck would I want to specify type if I'm using an image?!'. Well, the type will provide a fallback if something happens and the browser fails to load your image

::before Pseudo Selector

Another common way was to set the ::before selector

ul {
    li {list-style:none}
    li:before {content: "๐Ÿ˜Ž"}
}

Now...

::marker Pseudo Selector

What

The :marker pseudo selector applies list style attributes to a given element, whether you use <o;>, <ul> or any element given display: list-item. It's been in the draft spec for a while but now the browser support is really good, check it out on caniuse

Why

The previous examples still work fine, so why do you care if there's something new you can do?

This makes more sense semantically and it frees up the ::before selector. I've been given designs in the past where I've needed both the ::before and ::after selectors so I had to add extra mark-up to compensate. Now I can keep my mark-up neat and purposeful

How

Similar to the ::before selector, we can set the content of the bullet - but we don't need to remove the list style to avoid double bullets

marker.png

We can change the colour, content and size of the marker. We can also use a counter

li {
    counter-increment: item-counter;
}
li::marker {
    content: counter(item-counter);
}

marker-counter.png

Check out my pens for working demos

References

w3 org