Custom bullets with CSS ::marker

Browser Support

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 68.
  • Safari: 11.1.

Source

CSS ::marker lets you change the content and some of the styles of bullets and numbers in HTML lists.

Examples of bullet styles. View Source

Introduction to pseudo-elements

A pseudo-element represents a part in the document that isn't represented in the document tree. For example, you can select the first line of a paragraph using the pseudo-element p::first-line, even though there's no HTML element wrapping that line of text.

Consider the following HTML unordered list:

<ul>
  <li>Lorem ipsum dolor sit amet consectetur adipisicing elit</li>
  <li>Dolores quaerat illo totam porro</li>
  <li>Quidem aliquid perferendis voluptates</li>
  <li>Ipsa adipisci fugit assumenda dicta voluptates nihil reprehenderit
      consequatur alias facilis rem</li>
  <li>Fuga</li>
</ul>

Which renders as follows with default styling:

The dot at the start of each <ul> element is generated as part of rendering the list, and it doesn't have its own HTML element. ::marker is a pseudo-element representing that dot, or the number at the start of an ordered list element.

Create a marker

The ::marker pseudo-element marker box is automatically generated inside every list item element, before both the actual contents and the ::before pseudo-element.

li::before {
  content: "::before";
  background: lightgray;
  border-radius: 1ch;
  padding-inline: 1ch;
  margin-inline-end: 1ch;
}

List items are usually <li> HTML elements, but you can use display: list-item to turn other elements into list items.

<dl>
  <dt>Lorem</dt>
  <dd>Lorem ipsum dolor sit amet consectetur adipisicing elit</dd>
  <dd>Dolores quaerat illo totam porro</dd>

  <dt>Ipsum</dt>
  <dd>Quidem aliquid perferendis voluptates</dd>
</dl>
dd {
  display: list-item;
  list-style-type: "🤯";
  padding-inline-start: 1ch;
}

Style a marker

Before ::marker became available, you could style lists using list-style-type and list-style-image to change the list item symbol:

li {
  list-style-image: url(/right-arrow.svg);
  /* OR */
  list-style-type: '👉';
  padding-inline-start: 1ch;
}

::marker adds the ability to change the color, size, and spacing of markers by letting you target marker pseudo-elements individually or globally in your CSS:

li::marker {
  color: hotpink;
}

li:first-child::marker {
  font-size: 5rem;
}

::marker gives you far more control over marker styles than list-style-type, but it doesn't work with every CSS property. The following properties are allowed:

  • animation-*
  • transition-*
  • color
  • direction
  • font-*
  • content
  • unicode-bidi
  • white-space

Change the contents of a ::marker using content, not list-style-type. The next example shows how the properties of list-style-type apply to the whole list item, and ::marker lets you target just the marker box. The background property works with list-style-type, but not with ::marker.

List Styles
li:nth-child(1) {
  list-style-type: '?';
  font-size: 2rem;
  background: hsl(200 20% 88%);
  animation: color-change 3s ease-in-out infinite;
}
List styling affects the whole list item.
Marker Styles
li:nth-child(2)::marker {
  content: '!';
  font-size: 2rem;
  background: hsl(200 20% 88%);
  animation: color-change 3s ease-in-out infinite;
}
Marker styling lets you focus on the marker.


Change the content of a marker

Here are some example ways to style your markers.

Change all list items

li {
  list-style-type: "😍";
}

/* OR */

li::marker {
  content: "😍";
}

Change just one list item

li:last-child::marker {
  content: "😍";
}

Define markers with SVG

li::marker {
  content: url(/heart.svg);
  content: url(#heart);
  content: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='24' width='24'><path d='M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' fill='none' stroke='hotpink' stroke-width='3'/></svg>");
}

Change ordered lists

What about an <ol> though? The marker on an ordered list item is a number by default, not a dot or "bullet." In CSS, these are called Counters, and they have properties to set or reset where the number starts and ends, or switch them to, for example, Roman numerals. You can use ::marker to style counters too, and even use the marker content value to build your own numbering presentation.

li::marker {
  content: counter(list-item) "› ";
  color: hotpink;
}

Debug

Chrome DevTools cab help you inspect, debug and modify the styles you apply to ::marker pseudo-elements.

DevTools open and showing styles from the user agent and the user styles
DevTools descriptions of marker styles.

Resources

You can learn more about ::marker from: