Skip to content

fix: Keep page styles intact when filters navigate, and document the offset gotcha - #84

Merged
steveariss merged 1 commit into
mainfrom
fix/client-navigation-styles
Sep 13, 2026
Merged

steveariss merged 1 commit into
mainfrom
fix/client-navigation-styles

Conversation

@steveariss

Copy link
Copy Markdown
Collaborator

Problem

On a page with a Query Filter (reproduced on a local site at /insights/), changing a filter broke the styling of everything after the Query Loop until reload: eyebrow headings, a teal card, footer headings, link colours, and a WPForms honeypot field became visible ("Email Email Email").

Causes

Both come from how the Interactivity API router swaps a router region: it replaces the region's markup, but applies the fetched page's stylesheets to the whole document.

  1. Render-order class numbers. Block style variations (is-style-{name}--{n}, wp_unique_id()) and element styles (wp-elements-{n}, wp_unique_prefixed_id()) number their classes in render order. A different result count shifts every number after the loop, so the markup kept outside the region no longer matches the new CSS. Core fixed the same problem for layout classes by switching to hashes (Layout styles are incompatible with Interactivity API client-side navigation WordPress/gutenberg#67308); these two are still counters in WP 7.1.
  2. Script-injected styles. The router disables any stylesheet that isn't in the fetched HTML (iAPI Router: Support new styles and script modules on client-side navigation WordPress/gutenberg#70353). WPForms adds its honeypot CSS from an inline script, so it was switched off.

Fix

  • BlockFilters::reserve_unique_ids() (render_block_data) records both counters when a core/query block starts rendering. render_block_query() then advances them to start + 1,000, so blocks after the loop get the same numbers whatever it rendered. Class numbers after a Query Loop are now higher than before (e.g. is-style-eyebrow--2011).
  • view.js routes every navigation through one navigate() helper. Before the router first loads, it remembers id-less <style> / stylesheet <link> elements (WordPress gives every stylesheet it prints an id), then re-enables them after each navigation and on popstate. This covers filters, sort and search.
  • README troubleshooting entry: a Query Loop offset applies after the filter, so an offset used to skip a featured post can hide a term's only post.

Verification

  • 26 PHP tests and 9 JS tests pass; new tests were written first and seen failing. Lint is clean.
  • Live check on the reproducing site, comparing computed styles of the 312 elements outside the Query Loop before and after Articles → Impact Talks → browser Back:
Build Elements whose computed style changed
0.3.0 (control) 11–13 of 312: eyebrow headings, teal card, WPForms field, footer headings, links
This branch 1 of 312: the router's own a11y-speak announcer

Known limits

  • A style injected by a script after the first navigation isn't restored.
  • An id-less <style> that the server prints differently per page would keep its old copy enabled.
  • A Query Loop using more than 1,000 IDs falls back to the previous behaviour.

🤖 Generated with Claude Code

https://claude.ai/code/session_017jLNdSqi2eRVWCyTfQMGy7

…offset gotcha

After a filter changed, content after the Query Loop lost its styling until
reload. Two causes, both in how the Interactivity API router swaps a region:

- Block style variation (is-style-{name}--{n}) and element (wp-elements-{n})
  classes are numbered in render order. A different result count shifted the
  numbers, so markup after the loop no longer matched the new page's CSS.
  Each Query block now reserves 1,000 of these numbers.
- The router disables stylesheets missing from the fetched HTML, including
  styles injected by scripts (e.g. the WPForms honeypot CSS). view.js now
  re-enables id-less styles present before the router loaded, after each
  navigation and on back/forward.

Also adds a README troubleshooting entry: a Query Loop offset applies after
the filter, so it can hide a term's only post.
@github-actions github-actions Bot added bug Bug fix docs Documentation improvements labels Sep 13, 2026
@steveariss
steveariss merged commit fcb8f7d into main Sep 13, 2026
6 checks passed
@steveariss
steveariss deleted the fix/client-navigation-styles branch September 13, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix docs Documentation improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant