The ::marker pseudo-element in CSS lets you style the markers of list items – bullets, numbers, or anything you set via content. No extra HTML or JavaScript needed.
I use it regularly when the default bullet doesn’t fit the design, and it’s one of those small CSS features that makes a real difference in how polished a page feels.
Basic Usage
The basic syntax for using ::marker is straightforward. Apply it to list items in either unordered or ordered lists:
ul li::marker {
/* Styling for unordered list markers */
}
ol li::marker {
/* Styling for ordered list markers */
}The ::marker pseudo-element only supports a limited set of CSS properties: color, font-size, font-family, font-weight, font-style, content, direction, unicode-bidi, and animation-related properties. Properties like background-color, padding, or width do not work with ::marker.
Example 1: Customizing Bullets in an Unordered List
You can change the look of bullets in an unordered list by setting the content property on the marker:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>ul {
list-style: none;
font-size: 1.2rem;
font-family: 'Noto Sans Hebrew', sans-serif;
}
li {
padding-left: 7px;
}
li::marker {
content: "🔹";
}The content property replaces the default bullet with a blue diamond emoji.
Here is how it looks:
- Item 1
- Item 2
- Item 3
Example 2: Styling Numbers in an Ordered List
If you want the numbers in an ordered list to appear bold and red, you only need two properties:
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>li::marker {
font-weight: bold;
color: red;
}Here is the result:
- Item 1
- Item 2
- Item 3
Example 3: Advanced ::marker Example
This example builds a clickable task list where the bullet color reflects each task’s status. Since ::marker doesn’t support transforms or transitions, we use ::before instead.
The list items are displayed as flex containers to align the bullet and text. JavaScript toggles the status class on click, and a hover effect scales the bullet up slightly.
HTML
The markup defines a simple unordered list with status classes:
<ul>
<li class="completed"><span>Task 1: Completed</span></li>
<li class="in-progress"><span>Task 2: In Progress</span></li>
<li><span>Task 3: Incomplete</span></li>
</ul>CSS
The styles use ::before to create colored bullet markers that change based on the task status:
ul {
list-style: none;
padding: 0;
font-family: 'Noto Sans Hebrew', sans-serif;
font-size: 1.2rem;
}
li {
margin-bottom: 10px;
display: flex;
align-items: center;
cursor: pointer;
}
li::before {
content: '•';
display: inline-block;
width: 0.7em;
font-size: 1.5em;
color: #ddd;
transition: transform 0.3s, color 0.3s;
}
li.completed::before {
color: #4CAF50;
}
li.in-progress::before {
color: #FFC107;
}
li span {
flex-grow: 1;
}
li:hover::before {
transform: scale(1.2);
}JavaScript
A click handler toggles the task status between completed and in-progress:
document.addEventListener('DOMContentLoaded', function() {
const taskItems = document.querySelectorAll('li');
taskItems.forEach(function(item) {
item.addEventListener('click', function() {
this.classList.toggle('completed');
this.classList.toggle('in-progress');
});
});
});The Result
Click any task to toggle its status:
- Task 1: Completed
- Task 2: In Progress
- Task 3: Incomplete
When
::markerdoes not support the styling you need (such as backgrounds, transforms, or layout properties), using::beforewithlist-style: noneis a common workaround – as demonstrated in this advanced example.
::marker is not the only way to customize list appearance. For styling other text elements, take a look at the ::first-letter pseudo-element.
For more advanced selector techniques, check out the post on CSS4 selectors. And if you’re working with CSS nesting, you can nest ::marker rules right inside the parent selector for cleaner code.
FAQs
Common questions about the CSS ::marker pseudo-element:
::marker pseudo-element supports a limited set of properties: color, font-size, font-family, font-weight, font-style, content, direction, unicode-bidi, and animation-related properties. Properties like background, padding, width, and transform are not supported.::marker targets the existing list marker (bullet or number) and is limited to a small set of properties. ::before is a general pseudo-element that gives you full styling control but requires list-style: none to hide the default marker first. Use ::marker for simple color and font changes, and ::before when you need layout, backgrounds, or transforms.content property on ::marker to set any text, emoji, or Unicode character as the list marker. For example, li::marker { content: "🔹"; } replaces the default bullet with a blue diamond emoji.::marker applies to any element with display: list-item. By default, <li> elements have this display value. You can also apply display: list-item to other elements like <summary> or <div> to make ::marker work on them.::marker pseudo-element is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. For older browsers that do not support it, the default list markers will simply remain unchanged, making it a safe progressive enhancement.Summary
::marker handles the simple stuff well – color, font, and custom content with minimal code. When you need backgrounds, transforms, or layout control, drop down to ::before with list-style: none.
Both approaches are demonstrated in the live examples above. Pick the one that fits your needs.

