v156 · css · navigation

CSS pseudo-class for navigation source element

:navigation-source selects the element that started the current navigation — the clicked link, the submitted form, or the submit button — and keeps matching it for the whole course of that navigation. It is the CSS reflection of the Navigation API's source element, and it deletes the "add a class to whatever was clicked" script from every loading indicator and every view-transition naming dance.

concepts

  1. Loading links

    A navigation rail where the link you clicked shows its own in-flight state, styled by a:navigation-source during an intercepted same-document navigation — with the JS-classname pattern it replaces running beside it, labelled, on browsers that lack the selector.

  2. Form submit feedback

    The practical one: a form with two submit buttons where form:navigation-source and button:navigation-source style the submitting form and the exact button that fired, for the duration of the (deliberately slow) submission.

  3. Thumbnail view transition

    The motivating use case from the explainer: a:navigation-source .thumb { view-transition-name: hero } names the clicked thumbnail for a real view transition — one declaration instead of the set-name-then-clean-up JavaScript that SPAs do today. Both mechanisms run here, each labelled.

  4. Selector parse lab

    The inspection bench: parse probes for the exact selector, an @supports selector() rendering check, the idle no-match invariant, which elements are eligible sources, and a live sampler that measures how long the source element stays matched across a navigation.

why it shipped

View transitions made one question urgent: when a navigation starts, which element is it about? Expanding a thumbnail into a hero image needs the clicked thumbnail to carry a view-transition-name — but only that one, and only for this navigation. Until now the answer was JavaScript bookkeeping: listen for the click, set the name, start the transition, clean the name up afterwards so the next navigation doesn't break.

:navigation-source moves that bookkeeping into the selector. It matches any element that is the current navigation's source element — an <a>, <area>, <form>, submit <input> or <button> — while the navigation state is non-null, for same-document navigations (via the Navigation API's notion of an ongoing navigation) and cross-document ones (from initiation to the new page's first frame). Loading spinners on the clicked link, double-submit styling on the fired button, and view-transition naming all become plain CSS.

research record — use cases & exact surface

references