LEARNING OBJECTIVES ⌵
- Understand how the CSS
::markerpseudo-element targets list bullet and number boxes. - Master the strict subset of CSS properties supported on
::marker(color, font, content, text-transform). - Implement custom bullet glyphs, strings, emojis, and SVG data URIs.
- Compare
list-style-type: "..."with::marker { content: "..." }.
📖 The Mental Model & Story (Intuitive Foundation)
For decades, styling list bullets was one of the most frustrating tasks in web development.
If you wanted a simple red bullet with black text, you had to hack the DOM: wrap the inner text in a <span>, color the <li> red, and reset the <span> to black. If you wanted a checkmark emoji (✅) or a brand icon, developers had to set list-style: none and construct artificial markers using ::before pseudo-elements.
OLD BRITTLE HACK:
<li style="color: red;">
<span style="color: black;">List text</span>
</li>
MODERN CSS3 PSEUDO-ELEMENT STANDARD:
li::marker {
color: #ef4444;
font-size: 1.2em;
content: "🚀 ";
}
The CSS ::marker pseudo-element standardizes direct access to the generated marker box of any element with display: list-item. You can now colorize, resize, swap, and animate bullets natively without modifying HTML markup or breaking accessibility semantics.
Technical Deep Dive & Specifications
The Permitted CSS Properties on ::marker
The CSS Lists and Counters Module Level 3 restricts the properties that can be applied to ::marker to prevent layout reflow loops:
| Allowed CSS Property Group | Supported Properties |
|---|---|
| Content | content (strings, url(), counter(), counters()) |
| Color | color |
| Typography | font-family, font-size, font-weight, font-style, font-variant, line-height |
| Text Transformation | text-transform, letter-spacing, word-spacing |
| Direction & Bidi | direction, unicode-bidi |
| Transitions & Animations | transition, animation on allowed properties |
[!WARNING] Forbidden on
::marker: Box-model properties likemargin,padding,background,border,width,height, anddisplayhave NO EFFECT on::marker. If you need backgrounds or pill badges around markers, use::beforeon the<li>.
+--------------------------------------------+
| <li> Box |
| |
+--------------+ | +--------------------------------------+ |
| ::marker | | | Principal Content Box | |
| (Color, | | | "Unlimited API Requests" | |
| Font, | | | | |
| Content) | | | | |
+--------------+ | +--------------------------------------+ |
+--------------------------------------------+
Custom Strings with list-style-type vs. ::marker
You can customize list markers via two modern CSS mechanisms:
/* Method 1: list-style-type with custom string */
ul.emojis {
list-style-type: "👉 ";
}
/* Method 2: ::marker pseudo-element (more powerful) */
ul.custom-check li::marker {
content: "✅ ";
font-size: 1.1em;
}
ul.pricing-features li::marker {
color: #10b981; /* Only colors the marker, leaves text black! */
}
list-style-position: outside vs. inside
/* Default: Marker sits outside the content flow, aligned with margin */
ul.outside-marker {
list-style-position: outside; /* Default */
}
/* Inside: Marker is placed inside the first line of content text */
ul.inside-marker {
list-style-position: inside;
}
💻 Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 31–38:
.pro-list li::markerchanges the color of the native bullet to#3b82f6(blue) and increases its size to1.2emwithout needing inner wrapper<span>tags. - Lines 44–53:
.security-checklist li.pass::marker,li.warn::marker, andli.fail::markerinject custom emoji glyphs viacontent: "...". - Lines 73–78: The HTML remains pure, semantic
<ul>and<li>markup without artificial DOM overhead.
Expected Browser Render Output
+------------------------------------+ +------------------------------------+
| Enterprise Plan Features | | Security Audit Status |
| | | |
| [•] Dedicated Solutions Architect | | 🛡️ SOC-2 Type II Certification... |
| [•] Custom SAML SSO & SCIM Sync | | 🛡️ End-to-End Encryption Enabled |
| [•] 99.99% Uptime Financial SLA | | ⚠️ Pending 2FA Enrollment on 3... |
| [•] Automated Daily Backups | | 🚨 Open Port 22 Detected on... |
+------------------------------------+ +------------------------------------+
(Blue bullets) (Contextual emoji markers)🏋️ Hands-On Exercise
🎯 The Challenge: Build a Prioritized Incident Report
Construct an operational incident status list. Each item should have a custom visual marker reflecting its severity level using CSS ::marker.
Requirements:
- Use a semantic
<ul>list. - Define three severity classes:
.sev-critical: Marker must be a red exclamation stringcontent: "💥 "withcolor: #ef4444..sev-high: Marker must becontent: "🔥 "withcolor: #f97316..sev-resolved: Marker must becontent: "✅ "withcolor: #22c55e.
- Do not add any inner
<span>or extra DOM wrapper tags.
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Attempting to Set
backgroundon::marker: Writingli::marker { background: yellow; border-radius: 50%; }will fail silently because the CSS specification excludes box-model and background properties from::marker. - Forgetting Space After Custom Strings: When setting
content: "👉", the marker will touch the first letter of the text. Always include a trailing whitespace:content: "👉 ". - Using
list-style: noneWithoutrole="list": In WebKit (Safari), removing markers with CSS completely strips list semantics from VoiceOver. (Covered in detail in Lesson 7.9).
💡 Pro Tips
- SVG Data URIs in
::marker: You can render scalable vector icons directly as list markers usingcontent: url("data:image/svg+xml,...")without requesting external image assets. - The
@counter-styleRule: For internationalized numeral systems (e.g., custom Hebrew, Devanagari, or circled numbers①,②), use the modern CSS@counter-styleat-rule to define custom counting systems.
📌 Key Takeaways
- The CSS
::markerpseudo-element targets the marker box of anydisplay: list-itemelement. ::markersupports a strict property subset:color,font-*,content,text-transform, anddirection.- Box-model properties (
padding,margin,background,border) are not supported on::marker. - You can assign custom strings or emojis via
content: "🚀 "on::markerorlist-style-type: "🚀 "on the list. - Styling list markers with
::markerkeeps your HTML clean and preserves semantic accessibility. - --