The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Choose an unordered marker | .features { list-style-type: square; } | View examples |
| Choose an ordered style | .chapters { list-style-type: upper-roman; } | View examples |
| Keep markers outside | .checklist { list-style-position: outside; } | View examples |
| Style marker text | .checklist > li::marker {
color: #0f766e;
font-weight: 700;
} | View examples |
| Provide an image fallback | .links { list-style: circle outside url("arrow.svg"); } | View examples |
| Disable marker images | .plain { list-style-image: none; } | View examples |
| Use a short string marker | .steps { list-style-type: "→ "; } | View examples |
| Define a cyclic style | @counter-style status-dot {
system: cyclic;
symbols: "●";
suffix: " ";
fallback: disc;
} | View examples |
| Define fixed symbols | @counter-style circled-step {
system: fixed;
symbols: "①" "②" "③";
suffix: " ";
fallback: decimal;
} | View examples |
| Apply a named style | .milestones { list-style-type: circled-step; } | View examples |
| Create an anonymous style | .tags { list-style-type: symbols(cyclic "◆" "◇"); } | View examples |
| Set a list-item value | .resume-at-five { counter-set: list-item 4; } | View examples |
| Differentiate nested lists | .outline ul ul { list-style-type: circle; } | View examples |
| Feature-query ::marker | @supports selector(li::marker) {
li::marker { color: #0f766e; };
} | View examples |
| Keep real list markup | <ol><li>Download</li><li>Verify</li><li>Install</li></ol> | View examples |
List styling works best when CSS changes the presentation of genuine ol, ul, and li elements instead of rebuilding list semantics. Native list-item counters adapt automatically when items are inserted, removed, nested, reversed, or assigned explicit HTML values. Use ::marker for focused typographic changes, @counter-style for reusable numbering systems, and an ordinary list-style-type as the fallback whenever an image, symbol, or newer feature is unavailable.
Step by step
Detailed examples
Start with native markers and style ::marker selectively
list-style-type selects a built-in counter style or bullet, and list-style-position decides whether the marker participates in the first inline line or sits outside the principal list-item box. Outside is normally easier to scan when text wraps. The ::marker pseudo-element exposes the actual marker box, but its supported property set is intentionally narrower than a normal element. Prefer inheritable text properties such as color, font family, font size, and font weight; verify any more ambitious treatment in target browsers.
.features {
list-style-type: square;
list-style-position: outside;
padding-inline-start: 1.5rem;
}
.chapters { list-style-type: upper-roman; }
.features > li::marker {
color: #0f766e;
font-weight: 700;
}
.features > li + li { margin-block-start: 0.5rem; } Note: Logical padding keeps outside markers visible in both left-to-right and right-to-left writing directions.
Layer image and string markers over portable fallbacks
When list-style-image resolves to a usable image, it takes precedence over list-style-type; if the image cannot be used, the type remains the fallback. The list-style shorthand can declare image, type, and position together, but remember that every shorthand resets omitted longhands. Literal string marker values and generated images are less universally established than basic keywords, so put a widely supported declaration first. Keep network marker assets small: one cached SVG is cheaper and more stable than many unique images, but a native bullet avoids the request entirely.
.resource-links {
list-style-type: circle;
list-style-position: outside;
list-style-image: url("/icons/arrow-marker.svg");
}
.release-steps {
list-style-type: decimal;
list-style-type: "→ ";
}
.resource-links.no-images { list-style-image: none; } Note: Do not put unique state or instructions only in a marker image; its download and accessibility exposure are not guaranteed.
Define bounded, reusable counter styles with explicit fallback
@counter-style separates a numbering algorithm from the lists that consume it. The system descriptor determines how symbols are combined; suffix supplies punctuation after each representation, and fallback names the style used when the requested value cannot be represented. A fixed system naturally has a finite range, so decimal is a safe fallback beyond its symbols. The symbols() function is compact for local cyclic or symbolic markers, but a named rule is clearer when multiple components share the design. Unsupported at-rules are ignored, which makes a prior built-in list-style-type declaration essential.
@counter-style circled-step {
system: fixed;
symbols: "①" "②" "③";
suffix: " ";
fallback: decimal;
}
@counter-style status-dot {
system: cyclic;
symbols: "●";
suffix: " ";
fallback: disc;
}
.milestones {
list-style-type: decimal;
list-style-type: circled-step;
}
.tags {
list-style-type: disc;
list-style-type: symbols(cyclic "◆" "◇");
} Note: Keep symbol sets short and bounded. Pathological custom representations can consume unnecessary rendering memory for large counter values.
Preserve numbering continuity and nested hierarchy
Every list item participates in the implicit list-item counter, so native ordered lists already handle inserted items, reversed lists, and HTML start or value attributes. Use those HTML attributes when an ordinal is part of the content, because the number then survives missing styles and non-CSS formats. counter-set can make a presentational sequence resume at a chosen point, but it sets the value before the list item's normal increment. Descendant selectors can give each nesting level a distinct marker without changing the list tree.
<ol class="procedure" start="5">
<li>Deploy the canary
<ul>
<li>Check error rate</li>
<li>Check latency</li>
</ul>
</li>
<li>Expand traffic</li>
</ol> .procedure { list-style-type: decimal; }
.procedure ul { list-style-type: square; }
.procedure ul ul { list-style-type: circle; }
.resume-at-five { counter-set: list-item 4; } Note: Prefer start="5" or value="5" when five is meaningful data rather than a visual effect.
Treat marker design as progressive, nonessential presentation
An ol or ul with li children supplies durable list semantics before CSS loads and when custom marker support differs. Do not remove markers unless another visible treatment still makes every item boundary obvious, and do not rely on decorative symbols to communicate completed, failed, or required state. Marker pronunciation can vary across browser and assistive-technology combinations; although Counter Styles defines speak-as, support is still evolving, so real text must carry essential meaning. Feature queries can isolate ::marker enhancements, while the base list style remains usable. For long lists, native markers and shared rules also avoid extra DOM nodes and repeated image work.
<h2 id="release-title">Release checklist</h2>
<ol class="release-list" aria-labelledby="release-title">
<li><strong>Complete:</strong> tests passed</li>
<li><strong>Pending:</strong> production approval</li>
</ol> .release-list {
list-style-type: decimal;
padding-inline-start: 1.75rem;
}
@supports selector(li::marker) {
.release-list > li::marker {
color: #0f766e;
font-weight: 700;
}
} Note: The words Complete and Pending communicate state even if marker styling is absent or not announced.
Local code tester
Try resilient list marker systems
Edit native, custom, and nested markers while the underlying semantic list remains intact.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



