content fills ::before, ::after and ::marker (Pseudo-element Selectors) with strings, url() images, attr(name), open-quote/close-quote and counters. Create a counter with counter-reset, advance it with counter-increment and print it with counter(name), or with counters(name, ".") to join nested levels into outline numbers like 1.2. quotes lists the marks for each nesting level. Screen readers announce generated text, so give decorative content empty alternative text after a slash: content: "★" / "" (Baseline 2024).
<style>
body { font: 15px system-ui; margin: 8px; } q { quotes: "«" "»" "‹" "›"; }
ol { counter-reset: item; list-style: none; padding-left: 18px; margin: 0; }
li::before { counter-increment: item; content: counters(item, ".") ". "; color: #1565c0; }
a::after { content: " (" attr(href) ")"; color: #607d8b; }
</style>
<ol><li>Text properties<ol><li>Alignment</li><li>Spacing</li></ol></li>
<li>Graphic properties: <q>Say <q>cheese</q> to the gradient</q></li></ol>
<p>Details at <a href="https://example.com/details">the details page</a></p>