View Transitions JavaScript
Scope same-document view switching, history, focus, and native View Transition enhancement to each router.
Switch views with explicit button targets
Buttons can target views with `to`; the initializer updates active state, history, ARIA, focus, and animation together.
import { initializeViewTransitions } from "css-tags/view-transition.js";
<div data-view-transitions>
<button data-view-trigger to="summary" type="button">Summary</button>
<button data-view-trigger to="details" type="button">Details</button>
<section data-view-page id="summary" active>...</section>
<section data-view-page id="details">...</section>
</div>
initializeViewTransitions(document); Summary
Focus moves here after the transition update.
Details
This target does not require a URL hash.
More examples
Each example introduces a different part of the shipped API.
The enhancement synchronizes URL, focus, and state
After activation, the current trigger and visible page agree with the hash and focus moves to the new heading region.
import "css-tags/view-transition.js";
// Native hash links remain the fallback.
// The module enhances history, aria-current, visibility, and focus. href="#activity"aria-current="page"section[active][tabindex="-1"]view-transition.js enhances the CSS hash-link router. It is not required for cross-document transitions.
Setup
<div data-view-transitions> <nav aria-label="Account views"> <a data-view-trigger href="#profile">Profile</a> <a data-view-trigger href="#security">Security</a> </nav>
<section data-view-page id="profile" active> <h2>Profile</h2> </section>
<section data-view-page id="security"> <h2>Security</h2> </section></div>
<script type="module" src="/view-transition.js"></script>Each router manages only its own pages and triggers. Multiple routers can coexist without toggling one another’s content.
Supported hosts
- Router:
view-transitions,view-transition,[data-view-transitions],.view-transitions - Page:
view-page,[data-view-page],.view-page - Trigger:
nav-trigger,[data-view-trigger],.view-trigger
Triggers resolve their target from to="page-id" or a hash href="#page-id". Prefer native hash links.
Behavior
On activation, the enhancement:
- Marks one page
active. - Updates matching triggers with
aria-current="page". - Adds a hash history entry.
- Uses
document.startViewTransition()when supported and motion is allowed. - Focuses the new page after the transition update callback.
Back and forward navigation resynchronizes the active view from the URL hash. Unsupported browsers and reduced-motion users receive the same update without animation.
Programmatic initialization
The module initializes document routers automatically and exports its initializer for content rendered later:
import { initializeViewTransitions } from "/view-transition.js";
initializeViewTransitions(document.querySelector("#new-content"));Initialization is idempotent; routers already enhanced are skipped.
Custom elements
The optional custom trigger remains supported:
<nav-trigger to="profile" role="link" tabindex="0">Profile</nav-trigger>The enhancement supplies Enter and Space handling for this host, but native <a> and <button> elements remain preferable because their semantics work before JavaScript.