1<ul>2 <li>Tea</li>3 <li>Milk</li>4 <li>Bread</li>5</ul>index.html•✓TeaTea•✓MilkMilk•✓BreadBread1li:first-child {2 font-weight: bold; }3li:hover {4 color: tomato; }5li::before {6 content: "✓ "; }<li>element<li>element<li>element✓::before✓::before✓::before<li><li><li>123li:first-childboldli:hover✓✓✓0,1,10,1,10,0,2
Left: the two files, index.html (a list) and style.css (three rules)Right: the browser, the li elements (the DOM) and the dashed ::before boxesTokens: counts, selectors, the pointer, ticks and specificities on their wayLeft: the HTML file (a list of three items) and the CSS file (three rules). Right: the browser drawing the list, the tray of li elements (the DOM), and in front of it the ::before boxes CSS adds. li:first-child reaches only child 1, Tea, which turns bold. li:hover waits until the pointer is over Milk, which then turns tomato. li::before makes a new box with a tick for every item; the boxes are drawn but never join the DOM. A real browser works out every rule at once. The figure brings in one rule at a time so you can see what each one does. The page drawing is enlarged.

Pseudo-classes

  1. The HTML is a list: one ul holding three li items, Tea, Milk and Bread. The browser makes an element for each tag and draws them with bullets. Nothing in the tags says which item is first or which one the mouse is on.

Pseudo-elements

Telling them apart

What happens

;; step 1/10 · list
index.html
  <ul>
    <li>Tea</li>
    <li>Milk</li>
    <li>Bread</li>
  </ul>
elements (the DOM): ul with 3 li children
  li 1   "Tea"
  li 2   "Milk"
  li 3   "Bread"
browser default: ul { list-style-type: disc; }

A real browser works out every rule at once. The figure brings in one rule at a time so you can see what each one does. The page drawing is enlarged. The bullet is a pseudo-element too, ::marker. By default it sits outside the li's content, so the ::before box comes after the bullet and before the words.