Command Palette

Search for a command to run...

Hectal
PHASE 4Beginner ~20 min· topic 6 of 6

Topic 4.6

Styling Lists and Links

In one line

list-style and ::marker control the bullets and numbers of lists, and link styles are written in the order :link, :visited, :hover, :focus-visible, :active so each state wins at the right moment, while staying easy to spot for everyone.

Think of it like this

A shopping list and signposts. On a list, each item starts with a dot or a number (the marker) so your eye can count the items. A signpost (a link) must look like a signpost: if it blends into the wall, nobody follows it. It also changes when you've already been somewhere (visited), when you point at it (hover), and when you press it (active).

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Marker
The bullet or number shown before each list item.
list-style-type
Which kind of marker a list uses: disc, square, decimal, roman numerals, a string, or none.
list-style-position
Whether the marker sits outside the text (default) or inside it, as part of the first line.
::marker
The pseudo-element that styles the marker box of a list item.
Pseudo-class
A selector for a state, like :hover or :visited, written with one colon.
:visited
Matches links whose address is in the browser's history.
:focus-visible
Matches an element focused in a way that should show a focus ring, usually by keyboard.
:active
Matches a link or button while it's being pressed.
LVHFA
The order for link state rules: link, visited, hover, focus-visible, active.

Step by step

01Change the markers

Pick a marker type for each list. Ordered lists can count in letters or roman numerals; the start and reversed attributes in HTML still work.

style.csswhole filecss
ul.features {
  list-style-type: square;
}
ol.steps {
  list-style-type: upper-roman;
}
ul.arrows {
  list-style-type: "→ ";
}

02Colour the markers

::marker styles only the bullet or number, leaving the item text alone.

style.csswhole filecss
li::marker {
  color: tomato;
  font-weight: 700;
}

03Reset a list used as a menu

Navigation menus are lists of links. Remove the markers and the browser's padding and margin. Safari with VoiceOver may stop announcing "list, 4 items" once list-style: none is set, so add role="list" in the HTML when the list meaning matters.

style.csswhole filecss
nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

04Style link states in LVHFA order

Write the rules in this order. If :hover came before :visited, a visited link would ignore your hover colour, because the later :visited rule wins.

style.csswhole filecss
a:link { color: #1d4ed8; }
a:visited { color: #6d28d9; }
a:hover { color: #1e40af; text-decoration-thickness: 3px; }
a:focus-visible { outline: 3px solid #f59e0b; outline-offset: 2px; }
a:active { color: #b91c1c; }
Style link states in LVHFA orderdiagram
Rendering diagram…

05Keep links findable

Inside text, keep the underline and restyle it (Topic 4.4) rather than removing it. In navigation bars, where everything is a link, removing the underline is fine, but keep a clear hover and focus style.

style.csswhole filecss
article a {
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}
article a:hover {
  text-decoration-thickness: 2px;
}

Try it yourself

  1. 1

    Try other marker types

    In the first example, change upper-roman to lower-alpha, then decimal-leading-zero, then devanagari. Predict the second item's marker each time.

  2. 2

    Break the order on purpose

    In the second example, move the a:hover rule above a:link. Predict: does hovering still change the colour? It doesn't, because the later :link rule has the same specificity and wins. Put it back.

  3. 3

    Check the marker limits

    Add padding: 10px; background: yellow; to li::marker in the first example. Predict what changes. Nothing does: those properties aren't allowed on markers.

Code & diagrams

Marker types and ::marker New tab

`getComputedStyle(el, "::marker")` reads the marker's own styles. The 40px padding comes from the browser's built-in stylesheet.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

marker colour: rgb(255, 99, 71)
list-style-type: "→ "
default ul padding: 40px
A navigation list and link states New tab

Hover a link, press Tab to focus one with the keyboard, then press and hold the mouse button on one. Each state shows its style. (`display: flex` lays the menu out in a row; it's taught in the Flexbox phase.)

Preview

Press Run to see the page.

Console

Nothing logged yet.
Your own markers with ::before New tab

`::before` can have padding, backgrounds and positions that `::marker` won't accept. Positioning is taught in a later phase; here it pins the tick to the left of each item.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Hover written before visited

Write the link rules as a:hover { color: red; } then a:visited { color: purple; }.

terminal
$ the page shows
── what you'll see ──
Links you've already visited stay purple when hovered; only unvisited links turn red.

Break #2

Bullets gone but the indent stays

Set only list-style: none; on a menu <ul>.

terminal
$ DevTools → Computed
── what you'll see ──
padding-inline-start: 40px; margin-block: 16px (the menu still sits 40px to the right)

Break #3

Removing link underlines in body text

Set a { text-decoration: none; } on a page where links are only a slightly different blue from the text.

terminal
$ Lighthouse / axe
── what you'll see ──
Links rely on color to be distinguishable

Myth vs fact

Myth

list-style: none removes all list styling.

Fact

It removes the markers only. The browser's padding and margins stay until you reset them, and some screen readers may drop the list semantics.

Myth

You can style :visited links any way you like.

Fact

Browsers only allow colour changes for :visited and hide the result from JavaScript, to protect your browsing history.

Myth

Removing the focus outline makes the design cleaner and harms nobody.

Fact

Keyboard users rely on it to see where they are. Replace it with a clear :focus-visible style instead of deleting it.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Ordered list numbers are CSS counters: every li has display: list-item, which increments a built-in counter named list-item. You can use counter-reset, counter-increment and counter() for your own numbering (for example "Step 1:"), and @counter-style to define new marker systems.

  • ▸

    :visited styles are painted with the visited colour, but reading them back (getComputedStyle, element screenshots via canvas) returns the unvisited values. The colour's alpha channel is taken from the unvisited style, so :visited can't make a link transparent.

  • ▸

    :focus-visible uses browser heuristics: keyboard focus shows it, mouse clicks on links and buttons usually don't, and text inputs always do. That's why it replaced the old :focus { outline: none } habit; :focus alone also matches mouse focus.

  • ▸

    WebKit with VoiceOver removes list semantics from lists styled with list-style: none that aren't in a nav, a deliberate heuristic against "lists" used only for layout. Adding role="list" restores it. Check the current WebKit behaviour when it matters to you.

Remember this

  1. 1

    Lists (<ul> unordered, <ol> ordered, from the HTML course) show a marker before each <li>. list-style-type picks it: disc (●, the default for ul), circle, square, decimal (1, 2, 3, the default for ol), decimal-leading-zero (01, 02), lower-alpha, upper-roman, many language systems like devanagari, a string such as "→ ", or none. list-style-position puts the marker outside the text box (default) or inside it, and list-style-image uses a picture. The shorthand is list-style: square inside;.

  2. 2

    The browser gives lists padding-inline-start: 40px (left padding in English) so the outside markers have room, plus top and bottom margins. That's why a list with list-style: none still looks indented: remove the bullets and set padding: 0 (and margin: 0 if needed) for menus and card lists.

  3. 3

    ::marker is a pseudo-element (Phase 1) for the marker box itself. It accepts only a small set of properties: color, the font-* properties, content, white-space, direction, unicode-bidi, text-combine-upright, and animations/transitions of those. So li::marker { color: tomato; font-weight: 700; } works, but padding or background on a marker are ignored. For full control, people use list-style: none and draw their own marker with li::before.

  4. 4

    Links have states, each a pseudo-class: :link (not visited yet), :visited (already visited, from the browser's history), :hover (pointer over it), :focus-visible (focused by keyboard), and :active (being pressed). These selectors all have the same specificity (Phase 2), so the one written last wins when several apply. The order that works is L-V-H-F-A: :link, :visited, :hover, :focus-visible, :active, remembered as "LoVe Hate Focus Active" or "LoVe HAte".

  5. 5

    For privacy, :visited is limited: only colour properties (color, background-color, border-color, outline-color, text-decoration-color, column-rule-color, and SVG fill/stroke) can change, and getComputedStyle always reports the unvisited style. Otherwise a page could read your browsing history by checking which links are styled as visited.

  6. 6

    Accessible links: inside paragraphs, keep an underline (or another non-colour cue). WCAG 1.4.1 says colour can't be the only way to tell a link from text; if you remove the underline, the link colour needs at least 3:1 contrast with the surrounding text and a non-colour cue on hover and focus. Never remove focus outlines without replacing them (:focus-visible styles), make link text describe the destination (not "click here"), and give touch targets enough size.

Explain it without notes

01

Why must link state rules be written in LVHFA order?

02

Why is :visited restricted, and what can you still change with it?

03

What can ::marker style, and what do you do when you need more?

04

How do you keep links accessible if the design wants no underlines?

Practice

01

Make an ordered list count with lowercase letters and show the letters in bold seagreen.

02

Turn nav ul into a plain menu without bullets or indentation, and style its links in LVHFA order: blue, purple when visited, underlined on hover, an orange outline on keyboard focus, red while pressed.

Trade-offs

  • ↔

    ::marker keeps real list semantics and needs little CSS but allows only a few properties; a ::before marker is fully stylable but needs a reset and care with semantics.

  • ↔

    Underlined links are the most recognisable and accessible; underline-free links look cleaner but need extra contrast and hover/focus cues.

Done when you can

  • I can change list markers with list-style-type, position and the shorthand.

  • I can style markers with ::marker and know its limits.

  • I can reset a list for use as a menu.

  • I can write link states in LVHFA order and explain why.

  • I know what :visited may change and why.

  • I can keep links and focus states accessible.