Feat/atomic wind styles on dynamic pages#2921
Merged
Merged
Conversation
…for better CSS handling
The main content of a singular page is guaranteed to render, so its cached CSS can load speculatively in the head instead of the footer, removing the flash of unstyled content for the post itself. Hooked layouts and embeds stay on the render-tracked footer path. The head pass records the post in the expected/inlined maps so the footer collector neither duplicates the blob nor re-fetches the meta. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Bundle Size Diff
|
Contributor
|
Plugin build for c928a90 is ready 🛎️!
|
Contributor
E2E TestsPlaywright Test Status: See serial and parallel matrix jobs Performance ResultsserverResponse: {"q25":438.7,"q50":469.7,"q75":475.7,"cnt":10}, firstPaint: {"q25":1308.4,"q50":1483.5,"q75":1677.8,"cnt":10}, domContentLoaded: {"q25":3772.1,"q50":3787.25,"q75":3809.9,"cnt":10}, loaded: {"q25":3774.1,"q50":3789.1,"q75":3811.8,"cnt":10}, firstContentfulPaint: {"q25":4320,"q50":4326.6,"q75":4348.6,"cnt":10}, firstBlock: {"q25":14915.5,"q50":14968.75,"q75":15060.9,"cnt":10}, type: {"q25":28.91,"q50":29.61,"q75":33.64,"cnt":10}, typeWithoutInspector: {"q25":25.57,"q50":26.67,"q75":28.45,"cnt":10}, typeWithTopToolbar: {"q25":37.14,"q50":40.03,"q75":41.7,"cnt":10}, typeContainer: {"q25":17.96,"q50":19.07,"q75":23.43,"cnt":10}, focus: {"q25":154.93,"q50":165.41,"q75":169.9,"cnt":10}, inserterOpen: {"q25":45.29,"q50":50.21,"q75":54.28,"cnt":10}, inserterSearch: {"q25":18.45,"q50":19.03,"q75":22.35,"cnt":10}, inserterHover: {"q25":6.16,"q50":6.63,"q75":7.22,"cnt":20}, loadPatterns: {"q25":1922.15,"q50":1990.75,"q75":2011.26,"cnt":10}, listViewOpen: {"q25":261.23,"q50":293.25,"q75":297.49,"cnt":10} |
Soare-Robert-Daniel
approved these changes
Jul 16, 2026
Contributor
|
🎉 This PR is included in version 3.2.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Atomic Wind block styles now load wherever a post is displayed: single views, archives and search listings, and content attached via theme hooks (e.g. Neve Pro Custom Layouts on private post types). Previously they only loaded on singular pages via
global $post. The queried post's CSS loads in the head on singular views; everything else is gathered at render time, with an in-browser Tailwind generator as the correctness fallback.Changes
render_blocktracker counts renderedatomic-wind/*blocks per current post ID (skipping query-loop re-renders so counts stay aligned with raw content). Atwp_footerpriority 19, before WordPress prints footer assets at 20,output_late_cssinlines each tracked post's cached_atomic_wind_cssmeta into a single style tag, md5-deduped across posts.global $posthad the same structural hole as the old loader. Editor path unchanged.maybe_enqueue_style_builder): singular views only, queried post has Atomic Wind blocks, no cached CSS, current user can edit it. It regenerates and persists CSS via the existing REST route.Test instructions
Setup: enable Atomic Wind Blocks in Otter settings. You need one regular post with Atomic Wind blocks, and (for hook coverage) a Neve Pro Custom Layout containing Atomic Wind blocks, hooked to display on single posts.
<style id="atomic-wind-tailwind-inline-css">and the page does not loadtailwind-generator-frontend.js.<style id="atomic-wind-tailwind-late-inline-css">. The post's own CSS is not duplicated there.wp post meta delete <id> _atomic_wind_css) and reload logged out.tailwind-generator-frontend.jsloads and the blocks are styled after page load (brief flash is expected).style-builder.jsloads and the_atomic_wind_cssmeta is re-created (verify withwp post meta get <id> _atomic_wind_css); subsequent logged-out loads use the head inline style again, no generator.Note
wp_footer19). For above-the-fold hooked content (header layouts) a brief unstyled flash during progressive rendering is possible on slow connections. This is a deliberate trade-off: beyond the guaranteed-to-render singular post, CSS is gathered only for posts that actually display, with no speculative site-wide preloading and no extra queries or options.save_poststill clears a post's cached CSS on any update (including programmatic ones); pages self-heal via the generator until the next editor save re-warms the cache.Checklist before the final review