Skip to content

Use CSS navigation for chronological and pagination view transitions - #2

Draft
b1ink0 wants to merge 1 commit into
enhancement/add-chronological-pagination-transition-supportfrom
experimental/enhancement/add-chronological-pagination-transition-support
Draft

b1ink0 wants to merge 1 commit into
enhancement/add-chronological-pagination-transition-supportfrom
experimental/enhancement/add-chronological-pagination-transition-support

Conversation

@b1ink0

@b1ink0 b1ink0 commented Sep 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

Tests: WordPress#2336 (comment)

This PR adds directional view transitions for chronological and pagination navigation and experiments with moving direction detection from JavaScript to CSS using CSS Navigation Matching.

Direction detection works correctly for normal link navigation. However, there are still browser and WordPress limitations that prevent the implementation from being fully declarative.

Testing was done in Chrome Canary 154.0.8037.0 with chrome://flags/#enable-experimental-web-platform-features enabled.

Screen.Recording.2026-09-05.at.12.35.37.AM.mov

CSS Direction Detection

The server already knows the neighbouring URLs, so it can generate navigation rules directly:

@location --plvt-location-0 { pathname: "/category/uncategorized/"; }
@location --plvt-location-2 { pathname: "/category/uncategorized/page/:num(2|3|…|24)"; }

@navigation (from: --plvt-location-0) and (to: --plvt-location-2) {
	@view-transition {
		navigation: auto;
		types: chronological-forwards;
	}
}

This correctly resolves forward and backward direction, including jumps across multiple pages.

CSS Navigation Matching cannot currently compare captured numeric values, so the server generates URL patterns containing only the destinations valid for each direction.

Each generated @view-transition rule also needs to include navigation: auto, because matching rules replace each other rather than merging descriptors.

Both directions of a navigation pair must be generated so the transition can work on both the outgoing and incoming document.

Naming

The current chronological-* naming may be misleading because archive pagination and adjacent-post navigation move in opposite chronological directions while both follow a "next/previous" sequence.

Since these names may become public theme-support arguments, the naming should be confirmed before finalizing the API.

Known Limitations

Interactivity API

The WordPress Interactivity API calls history.replaceState() during page initialization.

This changes the navigation context so from: and to: can both resolve to the current URL, preventing the generated @navigation rule from matching.

This also affects JavaScript using navigation.activation.from, so the problem is not specific to CSS Navigation Matching.

Related:

This PR includes a temporary workaround that delays history.replaceState() until after pagereveal.

The workaround monkey-patches a browser API and should not be merged as the long-term solution.

Speculation Rules prerender

When a prerendered document is activated, the outgoing page detects the correct direction, but the incoming page does not match the @navigation rule.

The view transition still runs, but with no directional type, so it falls back to the default cross-fade.

This issue does not occur with prefetch.

This matters because WordPress already supports speculative loading and sites can switch the mode from prefetch to prerender.

Possible follow-up options include warning when directional transitions and prerender are both enabled, forcing prefetch, or excluding participating URLs from prerendering.

JavaScript Is Still Needed for Element Pairing

Direction detection can move to CSS, but cross-document element pairing still needs JavaScript.

For example, an archive thumbnail and the corresponding single-post hero image need the same view-transition-name, and the server does not know which archive link the user clicked.

view-transition-name: match-element only works for same-document transitions.

The spec includes a declarative solution through :navigation-source, but this is not yet available for use.

A server-side alternative would be to give every candidate element a deterministic transition name, but that may increase the number of elements the browser snapshots and has not been performance-tested.

Testing This Branch

Requires Chrome Canary 154.0.8037.0 or newer with:

chrome://flags/#enable-experimental-web-platform-features

enabled, followed by a full browser relaunch.

CSS Navigation Matching rules fail silently when unsupported or malformed, so confirm the feature is enabled before debugging:

const s = document.createElement( 'style' );
s.textContent = '@navigation (history: back) { :root { --x: 1 } }';
document.head.append( s );
console.log( 'route matching:', s.sheet.cssRules.length === 1 );

The branch also includes temporary navigation diagnostics through plvt_get_transition_diagnostics_script().

These diagnostics and the Interactivity API workaround must be removed before merge.

Relevant Technical Choices

  • Moved navigation direction detection from JavaScript to CSS Navigation Matching.
  • Generate directional URL patterns on the server because CSS cannot compare captured numeric values.
  • Use history: forward and history: back for traversal direction.
  • Keep JavaScript for cross-document element pairing until a declarative browser API is available.
  • Keep the Interactivity API workaround and navigation diagnostics temporary.

Use of AI Tools

Claude Opus 5 was used extensively for implementation, debugging, and investigation. The generated code and findings were reviewed and validated against browser behavior, specifications, Chromium source, and tests.

References

Spec and Design

WordPress

Browser Documentation

@b1ink0
b1ink0 marked this pull request as draft September 3, 2026 20:52
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: b1ink0 <b1ink0@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant