Skip to content

Conversation

@sjapaget
Copy link

@sjapaget sjapaget commented Oct 15, 2025

Use output buffering for template enhancement to reduce unnecessarily loaded CSS in classic themes. Makes use of wp_should_output_buffer_template_for_enhancement filter to delay the output of CSS until after the content is known and can be output by capturing the output of print_late_styles().

This is a core adaptation of the following feature plugin: https://gist.github.com/westonruter/99af37489334927aaf04a46eaf2a11eb

Trac ticket: https://core.trac.wordpress.org/ticket/64099

  • Compare markup before/after

This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@github-actions
Copy link

github-actions bot commented Oct 15, 2025

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.

Core Committers: Use this line as a base for the props when committing in SVN:

Props sjapaget, westonruter, peterwilsoncc, mindctrl.

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

@github-actions
Copy link

Hi @sjapaget! 👋

Thank you for your contribution to WordPress! 💖

It looks like this is your first pull request to wordpress-develop. Here are a few things to be aware of that may help you out!

No one monitors this repository for new pull requests. Pull requests must be attached to a Trac ticket to be considered for inclusion in WordPress Core. To attach a pull request to a Trac ticket, please include the ticket's full URL in your pull request description.

Pull requests are never merged on GitHub. The WordPress codebase continues to be managed through the SVN repository that this GitHub repository mirrors. Please feel free to open pull requests to work on any contribution you are making.

More information about how GitHub pull requests can be used to contribute to WordPress can be found in the Core Handbook.

Please include automated tests. Including tests in your pull request is one way to help your patch be considered faster. To learn about WordPress' test suites, visit the Automated Testing page in the handbook.

If you have not had a chance, please review the Contribute with Code page in the WordPress Core Handbook.

The Developer Hub also documents the various coding standards that are followed:

Thank you,
The WordPress Project

Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this!

@westonruter
Copy link
Member

We also need to add unit tests.

@westonruter
Copy link
Member

@sjapaget Do you anticipate being able to continue working on this before next week? The beta1 release is on Tuesday, so this needs to be completed quickly. If you don't have availability, I'll follow up with additional commits to get it to the finish line.

@sjapaget
Copy link
Author

sjapaget commented Oct 16, 2025

@sjapaget Do you anticipate being able to continue working on this before next week? The beta1 release is on Tuesday, so this needs to be completed quickly. If you don't have availability, I'll follow up with additional commits to get it to the finish line.

@westonruter I've done a bit more to it this afternoon (just pushed up) and will have time tomorrow too, but I'd very much appreciate some pointers on how to approach testing this properly if possible?

@sjapaget sjapaget requested a review from westonruter October 17, 2025 21:55
@peterwilsoncc peterwilsoncc force-pushed the block_styles_on_demand_in_classic_themes branch from 16b14dd to 2a2f97e Compare October 21, 2025 01:24
@westonruter
Copy link
Member

I'll commit this in the next hour.

Copy link
Contributor

@peterwilsoncc peterwilsoncc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing with T14, I've noticed this changes the order of CSS which could lead to problems.

On trunk, the core block styles are loaded prior to the themes block styles:

<link rel='stylesheet' id='wp-block-library-css' href='http://wp-dev.local/wp/wp-includes/css/dist/block-library/style.min.css?ver=6.9-alpha-60093-src' media='all' />
<!-- snip -->
<link rel='stylesheet' id='twentyfourteen-block-style-css' href='http://wp-dev.local/wp/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715' media='all' />

On this branch the core block styles are loaded after the themes block styles:

<link rel='stylesheet' id='twentyfourteen-block-style-css' href='http://wp-dev.local/wp/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715' media='all' />
<style id='wp-block-heading-inline-css'>
h1.has-background,h2.has-background,h3.has-background,h4.has-background,h5.has-background,h6.has-background{padding:1.25em 2.375em}h1.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h1.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h2.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h2.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h3.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h3.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h4.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h4.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h5.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h5.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h6.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h6.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]){rotate:180deg}
/*# sourceURL=http://wp-dev.local/wp/wp-includes/blocks/heading/style.min.css */
</style>
<style id='wp-block-archives-inline-css'>
.wp-block-archives{box-sizing:border-box}.wp-block-archives-dropdown label{display:block}
/*# sourceURL=http://wp-dev.local/wp/wp-includes/blocks/archives/style.min.css */
</style>
<!-- etc, etc -->

There's a risk this will end up breaking themes as the specificity of the relative styles will change with this code.

@westonruter
Copy link
Member

westonruter commented Oct 21, 2025

When not loading assets on demand:

add_filter( 'should_load_separate_core_block_assets', '__return_false', 1000 );
add_filter( 'should_load_block_assets_on_demand', '__return_false', 1000 );

The before/after diff shows the same order of cascade:

--- before.html	2025-10-20 20:15:28
+++ after.html	2025-10-20 20:15:28
@@ -418,6 +418,50 @@
       href="http://localhost:8000/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715"
       media="all"
     />
+    <style id="core-block-supports-inline-css">
+      /**
+ * Core styles: block-supports
+ */
+      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--50) * -1);
+        margin-left: calc(var(--wp--preset--spacing--50) * -1);
+      }
+      .wp-container-core-columns-is-layout-9d6595d7 {
+        flex-wrap: nowrap;
+      }
+      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
+        a:where(:not(.wp-element-button)) {
+        color: var(--wp--preset--color--base);
+      }
+      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--60) * -1);
+        margin-left: calc(var(--wp--preset--spacing--60) * -1);
+      }
+      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--30) * -1);
+        margin-left: calc(var(--wp--preset--spacing--30) * -1);
+      }
+      .wp-block-gallery.wp-block-gallery-2 {
+        --wp--style--unstable-gallery-gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+        gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+      }
+
+      /*# sourceURL=core-block-supports-inline-css */
+    </style>
+    <style id="core-block-supports-duotone-inline-css">
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
+        filter: url(#wp-duotone-f6cff4-ffee58-1);
+      }
+
+      /*# sourceURL=core-block-supports-duotone-inline-css */
+    </style>
     <script
       src="http://localhost:8000/wp-includes/js/jquery/jquery.js?ver=3.7.1"
       id="jquery-core-js"
@@ -3494,51 +3538,7 @@
         </filter>
       </defs>
     </svg>
-
-    <style id="core-block-supports-inline-css">
-      /**
- * Core styles: block-supports
- */
-      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--50) * -1);
-        margin-left: calc(var(--wp--preset--spacing--50) * -1);
-      }
-      .wp-container-core-columns-is-layout-9d6595d7 {
-        flex-wrap: nowrap;
-      }
-      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
-        a:where(:not(.wp-element-button)) {
-        color: var(--wp--preset--color--base);
-      }
-      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--60) * -1);
-        margin-left: calc(var(--wp--preset--spacing--60) * -1);
-      }
-      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--30) * -1);
-        margin-left: calc(var(--wp--preset--spacing--30) * -1);
-      }
-      .wp-block-gallery.wp-block-gallery-2 {
-        --wp--style--unstable-gallery-gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-        gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-      }
 
-      /*# sourceURL=core-block-supports-inline-css */
-    </style>
-    <style id="core-block-supports-duotone-inline-css">
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
-        filter: url(#wp-duotone-f6cff4-ffee58-1);
-      }
-
-      /*# sourceURL=core-block-supports-duotone-inline-css */
-    </style>
     <script
       src="http://localhost:8000/wp-includes/js/wp-embed.js?ver=6.9-alpha-60093-src"
       id="wp-embed-js"

What was previously printed in the wp_footer is now printed at wp_head, which is great as that reduces FOUC.

@westonruter
Copy link
Member

In contrast, when I force styles to be loaded on demand:

add_filter( 'should_load_separate_core_block_assets', '__return_true', 1000 );
add_filter( 'should_load_block_assets_on_demand', '__return_true', 1000 );

This is the diff I see:

--- before.html	2025-10-20 20:19:32
+++ after.html	2025-10-20 20:19:32
@@ -76,6 +76,506 @@
       href="http://localhost:8000/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715"
       media="all"
     />
+    <link
+      rel="stylesheet"
+      id="wp-block-image-css"
+      href="http://localhost:8000/wp-includes/blocks/image/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-image-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/image/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-paragraph-css"
+      href="http://localhost:8000/wp-includes/blocks/paragraph/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-group-css"
+      href="http://localhost:8000/wp-includes/blocks/group/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-group-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/group/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-pullquote-css"
+      href="http://localhost:8000/wp-includes/blocks/pullquote/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-pullquote-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/pullquote/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-columns-css"
+      href="http://localhost:8000/wp-includes/blocks/columns/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-cover-css"
+      href="http://localhost:8000/wp-includes/blocks/cover/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-social-links-css"
+      href="http://localhost:8000/wp-includes/blocks/social-links/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-embed-css"
+      href="http://localhost:8000/wp-includes/blocks/embed/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-embed-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/embed/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-categories-css"
+      href="http://localhost:8000/wp-includes/blocks/categories/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-gallery-css"
+      href="http://localhost:8000/wp-includes/blocks/gallery/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-gallery-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/gallery/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-search-css"
+      href="http://localhost:8000/wp-includes/blocks/search/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-search-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/search/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-heading-css"
+      href="http://localhost:8000/wp-includes/blocks/heading/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-latest-posts-css"
+      href="http://localhost:8000/wp-includes/blocks/latest-posts/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-latest-comments-css"
+      href="http://localhost:8000/wp-includes/blocks/latest-comments/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-archives-css"
+      href="http://localhost:8000/wp-includes/blocks/archives/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <style id="global-styles-inline-css">
+      :root {
+        --wp--preset--aspect-ratio--square: 1;
+        --wp--preset--aspect-ratio--4-3: 4/3;
+        --wp--preset--aspect-ratio--3-4: 3/4;
+        --wp--preset--aspect-ratio--3-2: 3/2;
+        --wp--preset--aspect-ratio--2-3: 2/3;
+        --wp--preset--aspect-ratio--16-9: 16/9;
+        --wp--preset--aspect-ratio--9-16: 9/16;
+        --wp--preset--color--black: #000;
+        --wp--preset--color--cyan-bluish-gray: #abb8c3;
+        --wp--preset--color--white: #fff;
+        --wp--preset--color--pale-pink: #f78da7;
+        --wp--preset--color--vivid-red: #cf2e2e;
+        --wp--preset--color--luminous-vivid-orange: #ff6900;
+        --wp--preset--color--luminous-vivid-amber: #fcb900;
+        --wp--preset--color--light-green-cyan: #7bdcb5;
+        --wp--preset--color--vivid-green-cyan: #00d084;
+        --wp--preset--color--pale-cyan-blue: #8ed1fc;
+        --wp--preset--color--vivid-cyan-blue: #0693e3;
+        --wp--preset--color--vivid-purple: #9b51e0;
+        --wp--preset--color--green: #24890d;
+        --wp--preset--color--dark-gray: #2b2b2b;
+        --wp--preset--color--medium-gray: #767676;
+        --wp--preset--color--light-gray: #f5f5f5;
+        --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(
+          135deg,
+          rgb(6, 147, 227) 0%,
+          rgb(155, 81, 224) 100%
+        );
+        --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(
+          135deg,
+          rgb(122, 220, 180) 0%,
+          rgb(0, 208, 130) 100%
+        );
+        --wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(
+          135deg,
+          rgb(252, 185, 0) 0%,
+          rgb(255, 105, 0) 100%
+        );
+        --wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(
+          135deg,
+          rgb(255, 105, 0) 0%,
+          rgb(207, 46, 46) 100%
+        );
+        --wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(
+          135deg,
+          rgb(238, 238, 238) 0%,
+          rgb(169, 184, 195) 100%
+        );
+        --wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(
+          135deg,
+          rgb(74, 234, 220) 0%,
+          rgb(151, 120, 209) 20%,
+          rgb(207, 42, 186) 40%,
+          rgb(238, 44, 130) 60%,
+          rgb(251, 105, 98) 80%,
+          rgb(254, 248, 76) 100%
+        );
+        --wp--preset--gradient--blush-light-purple: linear-gradient(
+          135deg,
+          rgb(255, 206, 236) 0%,
+          rgb(152, 150, 240) 100%
+        );
+        --wp--preset--gradient--blush-bordeaux: linear-gradient(
+          135deg,
+          rgb(254, 205, 165) 0%,
+          rgb(254, 45, 45) 50%,
+          rgb(107, 0, 62) 100%
+        );
+        --wp--preset--gradient--luminous-dusk: linear-gradient(
+          135deg,
+          rgb(255, 203, 112) 0%,
+          rgb(199, 81, 192) 50%,
+          rgb(65, 88, 208) 100%
+        );
+        --wp--preset--gradient--pale-ocean: linear-gradient(
+          135deg,
+          rgb(255, 245, 203) 0%,
+          rgb(182, 227, 212) 50%,
+          rgb(51, 167, 181) 100%
+        );
+        --wp--preset--gradient--electric-grass: linear-gradient(
+          135deg,
+          rgb(202, 248, 128) 0%,
+          rgb(113, 206, 126) 100%
+        );
+        --wp--preset--gradient--midnight: linear-gradient(
+          135deg,
+          rgb(2, 3, 129) 0%,
+          rgb(40, 116, 252) 100%
+        );
+        --wp--preset--font-size--small: 13px;
+        --wp--preset--font-size--medium: 20px;
+        --wp--preset--font-size--large: 36px;
+        --wp--preset--font-size--x-large: 42px;
+        --wp--preset--spacing--20: 0.44rem;
+        --wp--preset--spacing--30: 0.67rem;
+        --wp--preset--spacing--40: 1rem;
+        --wp--preset--spacing--50: 1.5rem;
+        --wp--preset--spacing--60: 2.25rem;
+        --wp--preset--spacing--70: 3.38rem;
+        --wp--preset--spacing--80: 5.06rem;
+        --wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);
+        --wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);
+        --wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);
+        --wp--preset--shadow--outlined:
+          6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);
+        --wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);
+      }
+      :where(.is-layout-flex) {
+        gap: 0.5em;
+      }
+      :where(.is-layout-grid) {
+        gap: 0.5em;
+      }
+      body .is-layout-flex {
+        display: flex;
+      }
+      .is-layout-flex {
+        flex-wrap: wrap;
+        align-items: center;
+      }
+      .is-layout-flex > :is(*, div) {
+        margin: 0;
+      }
+      body .is-layout-grid {
+        display: grid;
+      }
+      .is-layout-grid > :is(*, div) {
+        margin: 0;
+      }
+      :where(.wp-block-columns.is-layout-flex) {
+        gap: 2em;
+      }
+      :where(.wp-block-columns.is-layout-grid) {
+        gap: 2em;
+      }
+      :where(.wp-block-post-template.is-layout-flex) {
+        gap: 1.25em;
+      }
+      :where(.wp-block-post-template.is-layout-grid) {
+        gap: 1.25em;
+      }
+      .has-black-color {
+        color: var(--wp--preset--color--black) !important;
+      }
+      .has-cyan-bluish-gray-color {
+        color: var(--wp--preset--color--cyan-bluish-gray) !important;
+      }
+      .has-white-color {
+        color: var(--wp--preset--color--white) !important;
+      }
+      .has-pale-pink-color {
+        color: var(--wp--preset--color--pale-pink) !important;
+      }
+      .has-vivid-red-color {
+        color: var(--wp--preset--color--vivid-red) !important;
+      }
+      .has-luminous-vivid-orange-color {
+        color: var(--wp--preset--color--luminous-vivid-orange) !important;
+      }
+      .has-luminous-vivid-amber-color {
+        color: var(--wp--preset--color--luminous-vivid-amber) !important;
+      }
+      .has-light-green-cyan-color {
+        color: var(--wp--preset--color--light-green-cyan) !important;
+      }
+      .has-vivid-green-cyan-color {
+        color: var(--wp--preset--color--vivid-green-cyan) !important;
+      }
+      .has-pale-cyan-blue-color {
+        color: var(--wp--preset--color--pale-cyan-blue) !important;
+      }
+      .has-vivid-cyan-blue-color {
+        color: var(--wp--preset--color--vivid-cyan-blue) !important;
+      }
+      .has-vivid-purple-color {
+        color: var(--wp--preset--color--vivid-purple) !important;
+      }
+      .has-black-background-color {
+        background-color: var(--wp--preset--color--black) !important;
+      }
+      .has-cyan-bluish-gray-background-color {
+        background-color: var(--wp--preset--color--cyan-bluish-gray) !important;
+      }
+      .has-white-background-color {
+        background-color: var(--wp--preset--color--white) !important;
+      }
+      .has-pale-pink-background-color {
+        background-color: var(--wp--preset--color--pale-pink) !important;
+      }
+      .has-vivid-red-background-color {
+        background-color: var(--wp--preset--color--vivid-red) !important;
+      }
+      .has-luminous-vivid-orange-background-color {
+        background-color: var(
+          --wp--preset--color--luminous-vivid-orange
+        ) !important;
+      }
+      .has-luminous-vivid-amber-background-color {
+        background-color: var(
+          --wp--preset--color--luminous-vivid-amber
+        ) !important;
+      }
+      .has-light-green-cyan-background-color {
+        background-color: var(--wp--preset--color--light-green-cyan) !important;
+      }
+      .has-vivid-green-cyan-background-color {
+        background-color: var(--wp--preset--color--vivid-green-cyan) !important;
+      }
+      .has-pale-cyan-blue-background-color {
+        background-color: var(--wp--preset--color--pale-cyan-blue) !important;
+      }
+      .has-vivid-cyan-blue-background-color {
+        background-color: var(--wp--preset--color--vivid-cyan-blue) !important;
+      }
+      .has-vivid-purple-background-color {
+        background-color: var(--wp--preset--color--vivid-purple) !important;
+      }
+      .has-black-border-color {
+        border-color: var(--wp--preset--color--black) !important;
+      }
+      .has-cyan-bluish-gray-border-color {
+        border-color: var(--wp--preset--color--cyan-bluish-gray) !important;
+      }
+      .has-white-border-color {
+        border-color: var(--wp--preset--color--white) !important;
+      }
+      .has-pale-pink-border-color {
+        border-color: var(--wp--preset--color--pale-pink) !important;
+      }
+      .has-vivid-red-border-color {
+        border-color: var(--wp--preset--color--vivid-red) !important;
+      }
+      .has-luminous-vivid-orange-border-color {
+        border-color: var(
+          --wp--preset--color--luminous-vivid-orange
+        ) !important;
+      }
+      .has-luminous-vivid-amber-border-color {
+        border-color: var(--wp--preset--color--luminous-vivid-amber) !important;
+      }
+      .has-light-green-cyan-border-color {
+        border-color: var(--wp--preset--color--light-green-cyan) !important;
+      }
+      .has-vivid-green-cyan-border-color {
+        border-color: var(--wp--preset--color--vivid-green-cyan) !important;
+      }
+      .has-pale-cyan-blue-border-color {
+        border-color: var(--wp--preset--color--pale-cyan-blue) !important;
+      }
+      .has-vivid-cyan-blue-border-color {
+        border-color: var(--wp--preset--color--vivid-cyan-blue) !important;
+      }
+      .has-vivid-purple-border-color {
+        border-color: var(--wp--preset--color--vivid-purple) !important;
+      }
+      .has-vivid-cyan-blue-to-vivid-purple-gradient-background {
+        background: var(
+          --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple
+        ) !important;
+      }
+      .has-light-green-cyan-to-vivid-green-cyan-gradient-background {
+        background: var(
+          --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan
+        ) !important;
+      }
+      .has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background {
+        background: var(
+          --wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange
+        ) !important;
+      }
+      .has-luminous-vivid-orange-to-vivid-red-gradient-background {
+        background: var(
+          --wp--preset--gradient--luminous-vivid-orange-to-vivid-red
+        ) !important;
+      }
+      .has-very-light-gray-to-cyan-bluish-gray-gradient-background {
+        background: var(
+          --wp--preset--gradient--very-light-gray-to-cyan-bluish-gray
+        ) !important;
+      }
+      .has-cool-to-warm-spectrum-gradient-background {
+        background: var(
+          --wp--preset--gradient--cool-to-warm-spectrum
+        ) !important;
+      }
+      .has-blush-light-purple-gradient-background {
+        background: var(--wp--preset--gradient--blush-light-purple) !important;
+      }
+      .has-blush-bordeaux-gradient-background {
+        background: var(--wp--preset--gradient--blush-bordeaux) !important;
+      }
+      .has-luminous-dusk-gradient-background {
+        background: var(--wp--preset--gradient--luminous-dusk) !important;
+      }
+      .has-pale-ocean-gradient-background {
+        background: var(--wp--preset--gradient--pale-ocean) !important;
+      }
+      .has-electric-grass-gradient-background {
+        background: var(--wp--preset--gradient--electric-grass) !important;
+      }
+      .has-midnight-gradient-background {
+        background: var(--wp--preset--gradient--midnight) !important;
+      }
+      .has-small-font-size {
+        font-size: var(--wp--preset--font-size--small) !important;
+      }
+      .has-medium-font-size {
+        font-size: var(--wp--preset--font-size--medium) !important;
+      }
+      .has-large-font-size {
+        font-size: var(--wp--preset--font-size--large) !important;
+      }
+      .has-x-large-font-size {
+        font-size: var(--wp--preset--font-size--x-large) !important;
+      }
+      :where(.wp-block-columns.is-layout-flex) {
+        gap: 2em;
+      }
+      :where(.wp-block-columns.is-layout-grid) {
+        gap: 2em;
+      }
+      :root :where(.wp-block-pullquote) {
+        font-size: 1.5em;
+        line-height: 1.6;
+      }
+      /*# sourceURL=global-styles-inline-css */
+    </style>
+    <style id="core-block-supports-inline-css">
+      /**
+ * Core styles: block-supports
+ */
+      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--50) * -1);
+        margin-left: calc(var(--wp--preset--spacing--50) * -1);
+      }
+      .wp-container-core-columns-is-layout-9d6595d7 {
+        flex-wrap: nowrap;
+      }
+      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
+        a:where(:not(.wp-element-button)) {
+        color: var(--wp--preset--color--base);
+      }
+      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--60) * -1);
+        margin-left: calc(var(--wp--preset--spacing--60) * -1);
+      }
+      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--30) * -1);
+        margin-left: calc(var(--wp--preset--spacing--30) * -1);
+      }
+      .wp-block-gallery.wp-block-gallery-2 {
+        --wp--style--unstable-gallery-gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+        gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+      }
+
+      /*# sourceURL=core-block-supports-inline-css */
+    </style>
+    <style id="core-block-supports-duotone-inline-css">
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
+        filter: url(#wp-duotone-f6cff4-ffee58-1);
+      }
+
+      /*# sourceURL=core-block-supports-duotone-inline-css */
+    </style>
     <script
       src="http://localhost:8000/wp-includes/js/jquery/jquery.js?ver=3.7.1"
       id="jquery-core-js"
@@ -3152,507 +3652,7 @@
         </filter>
       </defs>
     </svg>
-
-    <link
-      rel="stylesheet"
-      id="wp-block-image-css"
-      href="http://localhost:8000/wp-includes/blocks/image/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-image-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/image/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-paragraph-css"
-      href="http://localhost:8000/wp-includes/blocks/paragraph/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-group-css"
-      href="http://localhost:8000/wp-includes/blocks/group/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-group-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/group/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-pullquote-css"
-      href="http://localhost:8000/wp-includes/blocks/pullquote/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-pullquote-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/pullquote/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-columns-css"
-      href="http://localhost:8000/wp-includes/blocks/columns/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-cover-css"
-      href="http://localhost:8000/wp-includes/blocks/cover/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-social-links-css"
-      href="http://localhost:8000/wp-includes/blocks/social-links/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-embed-css"
-      href="http://localhost:8000/wp-includes/blocks/embed/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-embed-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/embed/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-categories-css"
-      href="http://localhost:8000/wp-includes/blocks/categories/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-gallery-css"
-      href="http://localhost:8000/wp-includes/blocks/gallery/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-gallery-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/gallery/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-search-css"
-      href="http://localhost:8000/wp-includes/blocks/search/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-search-theme-css"
-      href="http://localhost:8000/wp-includes/blocks/search/theme.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-heading-css"
-      href="http://localhost:8000/wp-includes/blocks/heading/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-latest-posts-css"
-      href="http://localhost:8000/wp-includes/blocks/latest-posts/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-latest-comments-css"
-      href="http://localhost:8000/wp-includes/blocks/latest-comments/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="wp-block-archives-css"
-      href="http://localhost:8000/wp-includes/blocks/archives/style.css?ver=6.9-alpha-60093-src"
-      media="all"
-    />
-    <style id="global-styles-inline-css">
-      :root {
-        --wp--preset--aspect-ratio--square: 1;
-        --wp--preset--aspect-ratio--4-3: 4/3;
-        --wp--preset--aspect-ratio--3-4: 3/4;
-        --wp--preset--aspect-ratio--3-2: 3/2;
-        --wp--preset--aspect-ratio--2-3: 2/3;
-        --wp--preset--aspect-ratio--16-9: 16/9;
-        --wp--preset--aspect-ratio--9-16: 9/16;
-        --wp--preset--color--black: #000;
-        --wp--preset--color--cyan-bluish-gray: #abb8c3;
-        --wp--preset--color--white: #fff;
-        --wp--preset--color--pale-pink: #f78da7;
-        --wp--preset--color--vivid-red: #cf2e2e;
-        --wp--preset--color--luminous-vivid-orange: #ff6900;
-        --wp--preset--color--luminous-vivid-amber: #fcb900;
-        --wp--preset--color--light-green-cyan: #7bdcb5;
-        --wp--preset--color--vivid-green-cyan: #00d084;
-        --wp--preset--color--pale-cyan-blue: #8ed1fc;
-        --wp--preset--color--vivid-cyan-blue: #0693e3;
-        --wp--preset--color--vivid-purple: #9b51e0;
-        --wp--preset--color--green: #24890d;
-        --wp--preset--color--dark-gray: #2b2b2b;
-        --wp--preset--color--medium-gray: #767676;
-        --wp--preset--color--light-gray: #f5f5f5;
-        --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(
-          135deg,
-          rgb(6, 147, 227) 0%,
-          rgb(155, 81, 224) 100%
-        );
-        --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(
-          135deg,
-          rgb(122, 220, 180) 0%,
-          rgb(0, 208, 130) 100%
-        );
-        --wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(
-          135deg,
-          rgb(252, 185, 0) 0%,
-          rgb(255, 105, 0) 100%
-        );
-        --wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(
-          135deg,
-          rgb(255, 105, 0) 0%,
-          rgb(207, 46, 46) 100%
-        );
-        --wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(
-          135deg,
-          rgb(238, 238, 238) 0%,
-          rgb(169, 184, 195) 100%
-        );
-        --wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(
-          135deg,
-          rgb(74, 234, 220) 0%,
-          rgb(151, 120, 209) 20%,
-          rgb(207, 42, 186) 40%,
-          rgb(238, 44, 130) 60%,
-          rgb(251, 105, 98) 80%,
-          rgb(254, 248, 76) 100%
-        );
-        --wp--preset--gradient--blush-light-purple: linear-gradient(
-          135deg,
-          rgb(255, 206, 236) 0%,
-          rgb(152, 150, 240) 100%
-        );
-        --wp--preset--gradient--blush-bordeaux: linear-gradient(
-          135deg,
-          rgb(254, 205, 165) 0%,
-          rgb(254, 45, 45) 50%,
-          rgb(107, 0, 62) 100%
-        );
-        --wp--preset--gradient--luminous-dusk: linear-gradient(
-          135deg,
-          rgb(255, 203, 112) 0%,
-          rgb(199, 81, 192) 50%,
-          rgb(65, 88, 208) 100%
-        );
-        --wp--preset--gradient--pale-ocean: linear-gradient(
-          135deg,
-          rgb(255, 245, 203) 0%,
-          rgb(182, 227, 212) 50%,
-          rgb(51, 167, 181) 100%
-        );
-        --wp--preset--gradient--electric-grass: linear-gradient(
-          135deg,
-          rgb(202, 248, 128) 0%,
-          rgb(113, 206, 126) 100%
-        );
-        --wp--preset--gradient--midnight: linear-gradient(
-          135deg,
-          rgb(2, 3, 129) 0%,
-          rgb(40, 116, 252) 100%
-        );
-        --wp--preset--font-size--small: 13px;
-        --wp--preset--font-size--medium: 20px;
-        --wp--preset--font-size--large: 36px;
-        --wp--preset--font-size--x-large: 42px;
-        --wp--preset--spacing--20: 0.44rem;
-        --wp--preset--spacing--30: 0.67rem;
-        --wp--preset--spacing--40: 1rem;
-        --wp--preset--spacing--50: 1.5rem;
-        --wp--preset--spacing--60: 2.25rem;
-        --wp--preset--spacing--70: 3.38rem;
-        --wp--preset--spacing--80: 5.06rem;
-        --wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);
-        --wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);
-        --wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);
-        --wp--preset--shadow--outlined:
-          6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);
-        --wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);
-      }
-      :where(.is-layout-flex) {
-        gap: 0.5em;
-      }
-      :where(.is-layout-grid) {
-        gap: 0.5em;
-      }
-      body .is-layout-flex {
-        display: flex;
-      }
-      .is-layout-flex {
-        flex-wrap: wrap;
-        align-items: center;
-      }
-      .is-layout-flex > :is(*, div) {
-        margin: 0;
-      }
-      body .is-layout-grid {
-        display: grid;
-      }
-      .is-layout-grid > :is(*, div) {
-        margin: 0;
-      }
-      :where(.wp-block-columns.is-layout-flex) {
-        gap: 2em;
-      }
-      :where(.wp-block-columns.is-layout-grid) {
-        gap: 2em;
-      }
-      :where(.wp-block-post-template.is-layout-flex) {
-        gap: 1.25em;
-      }
-      :where(.wp-block-post-template.is-layout-grid) {
-        gap: 1.25em;
-      }
-      .has-black-color {
-        color: var(--wp--preset--color--black) !important;
-      }
-      .has-cyan-bluish-gray-color {
-        color: var(--wp--preset--color--cyan-bluish-gray) !important;
-      }
-      .has-white-color {
-        color: var(--wp--preset--color--white) !important;
-      }
-      .has-pale-pink-color {
-        color: var(--wp--preset--color--pale-pink) !important;
-      }
-      .has-vivid-red-color {
-        color: var(--wp--preset--color--vivid-red) !important;
-      }
-      .has-luminous-vivid-orange-color {
-        color: var(--wp--preset--color--luminous-vivid-orange) !important;
-      }
-      .has-luminous-vivid-amber-color {
-        color: var(--wp--preset--color--luminous-vivid-amber) !important;
-      }
-      .has-light-green-cyan-color {
-        color: var(--wp--preset--color--light-green-cyan) !important;
-      }
-      .has-vivid-green-cyan-color {
-        color: var(--wp--preset--color--vivid-green-cyan) !important;
-      }
-      .has-pale-cyan-blue-color {
-        color: var(--wp--preset--color--pale-cyan-blue) !important;
-      }
-      .has-vivid-cyan-blue-color {
-        color: var(--wp--preset--color--vivid-cyan-blue) !important;
-      }
-      .has-vivid-purple-color {
-        color: var(--wp--preset--color--vivid-purple) !important;
-      }
-      .has-black-background-color {
-        background-color: var(--wp--preset--color--black) !important;
-      }
-      .has-cyan-bluish-gray-background-color {
-        background-color: var(--wp--preset--color--cyan-bluish-gray) !important;
-      }
-      .has-white-background-color {
-        background-color: var(--wp--preset--color--white) !important;
-      }
-      .has-pale-pink-background-color {
-        background-color: var(--wp--preset--color--pale-pink) !important;
-      }
-      .has-vivid-red-background-color {
-        background-color: var(--wp--preset--color--vivid-red) !important;
-      }
-      .has-luminous-vivid-orange-background-color {
-        background-color: var(
-          --wp--preset--color--luminous-vivid-orange
-        ) !important;
-      }
-      .has-luminous-vivid-amber-background-color {
-        background-color: var(
-          --wp--preset--color--luminous-vivid-amber
-        ) !important;
-      }
-      .has-light-green-cyan-background-color {
-        background-color: var(--wp--preset--color--light-green-cyan) !important;
-      }
-      .has-vivid-green-cyan-background-color {
-        background-color: var(--wp--preset--color--vivid-green-cyan) !important;
-      }
-      .has-pale-cyan-blue-background-color {
-        background-color: var(--wp--preset--color--pale-cyan-blue) !important;
-      }
-      .has-vivid-cyan-blue-background-color {
-        background-color: var(--wp--preset--color--vivid-cyan-blue) !important;
-      }
-      .has-vivid-purple-background-color {
-        background-color: var(--wp--preset--color--vivid-purple) !important;
-      }
-      .has-black-border-color {
-        border-color: var(--wp--preset--color--black) !important;
-      }
-      .has-cyan-bluish-gray-border-color {
-        border-color: var(--wp--preset--color--cyan-bluish-gray) !important;
-      }
-      .has-white-border-color {
-        border-color: var(--wp--preset--color--white) !important;
-      }
-      .has-pale-pink-border-color {
-        border-color: var(--wp--preset--color--pale-pink) !important;
-      }
-      .has-vivid-red-border-color {
-        border-color: var(--wp--preset--color--vivid-red) !important;
-      }
-      .has-luminous-vivid-orange-border-color {
-        border-color: var(
-          --wp--preset--color--luminous-vivid-orange
-        ) !important;
-      }
-      .has-luminous-vivid-amber-border-color {
-        border-color: var(--wp--preset--color--luminous-vivid-amber) !important;
-      }
-      .has-light-green-cyan-border-color {
-        border-color: var(--wp--preset--color--light-green-cyan) !important;
-      }
-      .has-vivid-green-cyan-border-color {
-        border-color: var(--wp--preset--color--vivid-green-cyan) !important;
-      }
-      .has-pale-cyan-blue-border-color {
-        border-color: var(--wp--preset--color--pale-cyan-blue) !important;
-      }
-      .has-vivid-cyan-blue-border-color {
-        border-color: var(--wp--preset--color--vivid-cyan-blue) !important;
-      }
-      .has-vivid-purple-border-color {
-        border-color: var(--wp--preset--color--vivid-purple) !important;
-      }
-      .has-vivid-cyan-blue-to-vivid-purple-gradient-background {
-        background: var(
-          --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple
-        ) !important;
-      }
-      .has-light-green-cyan-to-vivid-green-cyan-gradient-background {
-        background: var(
-          --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan
-        ) !important;
-      }
-      .has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background {
-        background: var(
-          --wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange
-        ) !important;
-      }
-      .has-luminous-vivid-orange-to-vivid-red-gradient-background {
-        background: var(
-          --wp--preset--gradient--luminous-vivid-orange-to-vivid-red
-        ) !important;
-      }
-      .has-very-light-gray-to-cyan-bluish-gray-gradient-background {
-        background: var(
-          --wp--preset--gradient--very-light-gray-to-cyan-bluish-gray
-        ) !important;
-      }
-      .has-cool-to-warm-spectrum-gradient-background {
-        background: var(
-          --wp--preset--gradient--cool-to-warm-spectrum
-        ) !important;
-      }
-      .has-blush-light-purple-gradient-background {
-        background: var(--wp--preset--gradient--blush-light-purple) !important;
-      }
-      .has-blush-bordeaux-gradient-background {
-        background: var(--wp--preset--gradient--blush-bordeaux) !important;
-      }
-      .has-luminous-dusk-gradient-background {
-        background: var(--wp--preset--gradient--luminous-dusk) !important;
-      }
-      .has-pale-ocean-gradient-background {
-        background: var(--wp--preset--gradient--pale-ocean) !important;
-      }
-      .has-electric-grass-gradient-background {
-        background: var(--wp--preset--gradient--electric-grass) !important;
-      }
-      .has-midnight-gradient-background {
-        background: var(--wp--preset--gradient--midnight) !important;
-      }
-      .has-small-font-size {
-        font-size: var(--wp--preset--font-size--small) !important;
-      }
-      .has-medium-font-size {
-        font-size: var(--wp--preset--font-size--medium) !important;
-      }
-      .has-large-font-size {
-        font-size: var(--wp--preset--font-size--large) !important;
-      }
-      .has-x-large-font-size {
-        font-size: var(--wp--preset--font-size--x-large) !important;
-      }
-      :where(.wp-block-columns.is-layout-flex) {
-        gap: 2em;
-      }
-      :where(.wp-block-columns.is-layout-grid) {
-        gap: 2em;
-      }
-      :root :where(.wp-block-pullquote) {
-        font-size: 1.5em;
-        line-height: 1.6;
-      }
-      /*# sourceURL=global-styles-inline-css */
-    </style>
-    <style id="core-block-supports-inline-css">
-      /**
- * Core styles: block-supports
- */
-      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--50) * -1);
-        margin-left: calc(var(--wp--preset--spacing--50) * -1);
-      }
-      .wp-container-core-columns-is-layout-9d6595d7 {
-        flex-wrap: nowrap;
-      }
-      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
-        a:where(:not(.wp-element-button)) {
-        color: var(--wp--preset--color--base);
-      }
-      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--60) * -1);
-        margin-left: calc(var(--wp--preset--spacing--60) * -1);
-      }
-      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--30) * -1);
-        margin-left: calc(var(--wp--preset--spacing--30) * -1);
-      }
-      .wp-block-gallery.wp-block-gallery-2 {
-        --wp--style--unstable-gallery-gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-        gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-      }
-
-      /*# sourceURL=core-block-supports-inline-css */
-    </style>
-    <style id="core-block-supports-duotone-inline-css">
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
-        filter: url(#wp-duotone-f6cff4-ffee58-1);
-      }
 
-      /*# sourceURL=core-block-supports-duotone-inline-css */
-    </style>
     <script
       src="http://localhost:8000/wp-includes/js/wp-embed.js?ver=6.9-alpha-60093-src"
       id="wp-embed-js"

Again, the cascade is the same, with the benefit of FOUC elimination.

@westonruter
Copy link
Member

And here is the diff when before the styles are not loaded on demand, but after they are:

--- before.html	2025-10-20 20:25:07
+++ after.html	2025-10-20 20:25:07
@@ -43,21 +43,165 @@
     <link
       rel="stylesheet"
       id="wp-block-library-css"
-      href="http://localhost:8000/wp-includes/css/dist/block-library/style.css?ver=6.9-alpha-60093-src"
+      href="http://localhost:8000/wp-includes/css/dist/block-library/common.css?ver=6.9-alpha-60093-src"
       media="all"
     />
     <link
       rel="stylesheet"
-      id="wp-block-library-theme-css"
-      href="http://localhost:8000/wp-includes/css/dist/block-library/theme.css?ver=6.9-alpha-60093-src"
+      id="classic-theme-styles-css"
+      href="http://localhost:8000/wp-includes/css/classic-themes.css?ver=6.9-alpha-60093-src"
       media="all"
     />
     <link
       rel="stylesheet"
-      id="classic-theme-styles-css"
-      href="http://localhost:8000/wp-includes/css/classic-themes.css?ver=6.9-alpha-60093-src"
+      id="twentyfourteen-lato-css"
+      href="http://localhost:8000/wp-content/themes/twentyfourteen/fonts/font-lato.css?ver=20230328"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="genericons-css"
+      href="http://localhost:8000/wp-content/themes/twentyfourteen/genericons/genericons.css?ver=3.0.3"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="twentyfourteen-style-css"
+      href="http://localhost:8000/wp-content/themes/twentyfourteen/style.css?ver=20250715"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="twentyfourteen-block-style-css"
+      href="http://localhost:8000/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-image-css"
+      href="http://localhost:8000/wp-includes/blocks/image/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-image-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/image/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-paragraph-css"
+      href="http://localhost:8000/wp-includes/blocks/paragraph/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-group-css"
+      href="http://localhost:8000/wp-includes/blocks/group/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-group-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/group/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-pullquote-css"
+      href="http://localhost:8000/wp-includes/blocks/pullquote/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-pullquote-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/pullquote/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-columns-css"
+      href="http://localhost:8000/wp-includes/blocks/columns/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-cover-css"
+      href="http://localhost:8000/wp-includes/blocks/cover/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-social-links-css"
+      href="http://localhost:8000/wp-includes/blocks/social-links/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-embed-css"
+      href="http://localhost:8000/wp-includes/blocks/embed/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-embed-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/embed/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-categories-css"
+      href="http://localhost:8000/wp-includes/blocks/categories/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-gallery-css"
+      href="http://localhost:8000/wp-includes/blocks/gallery/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-gallery-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/gallery/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-search-css"
+      href="http://localhost:8000/wp-includes/blocks/search/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-search-theme-css"
+      href="http://localhost:8000/wp-includes/blocks/search/theme.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-heading-css"
+      href="http://localhost:8000/wp-includes/blocks/heading/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-latest-posts-css"
+      href="http://localhost:8000/wp-includes/blocks/latest-posts/style.css?ver=6.9-alpha-60093-src"
       media="all"
     />
+    <link
+      rel="stylesheet"
+      id="wp-block-latest-comments-css"
+      href="http://localhost:8000/wp-includes/blocks/latest-comments/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
+    <link
+      rel="stylesheet"
+      id="wp-block-archives-css"
+      href="http://localhost:8000/wp-includes/blocks/archives/style.css?ver=6.9-alpha-60093-src"
+      media="all"
+    />
     <style id="global-styles-inline-css">
       :root {
         --wp--preset--aspect-ratio--square: 1;
@@ -376,12 +520,6 @@
       .has-x-large-font-size {
         font-size: var(--wp--preset--font-size--x-large) !important;
       }
-      :where(.wp-block-post-template.is-layout-flex) {
-        gap: 1.25em;
-      }
-      :where(.wp-block-post-template.is-layout-grid) {
-        gap: 1.25em;
-      }
       :where(.wp-block-columns.is-layout-flex) {
         gap: 2em;
       }
@@ -394,30 +532,50 @@
       }
       /*# sourceURL=global-styles-inline-css */
     </style>
-    <link
-      rel="stylesheet"
-      id="twentyfourteen-lato-css"
-      href="http://localhost:8000/wp-content/themes/twentyfourteen/fonts/font-lato.css?ver=20230328"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="genericons-css"
-      href="http://localhost:8000/wp-content/themes/twentyfourteen/genericons/genericons.css?ver=3.0.3"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="twentyfourteen-style-css"
-      href="http://localhost:8000/wp-content/themes/twentyfourteen/style.css?ver=20250715"
-      media="all"
-    />
-    <link
-      rel="stylesheet"
-      id="twentyfourteen-block-style-css"
-      href="http://localhost:8000/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715"
-      media="all"
-    />
+    <style id="core-block-supports-inline-css">
+      /**
+ * Core styles: block-supports
+ */
+      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--50) * -1);
+        margin-left: calc(var(--wp--preset--spacing--50) * -1);
+      }
+      .wp-container-core-columns-is-layout-9d6595d7 {
+        flex-wrap: nowrap;
+      }
+      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
+        a:where(:not(.wp-element-button)) {
+        color: var(--wp--preset--color--base);
+      }
+      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--60) * -1);
+        margin-left: calc(var(--wp--preset--spacing--60) * -1);
+      }
+      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
+        margin-right: calc(var(--wp--preset--spacing--30) * -1);
+        margin-left: calc(var(--wp--preset--spacing--30) * -1);
+      }
+      .wp-block-gallery.wp-block-gallery-2 {
+        --wp--style--unstable-gallery-gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+        gap: var(
+          --wp--style--gallery-gap-default,
+          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
+        );
+      }
+
+      /*# sourceURL=core-block-supports-inline-css */
+    </style>
+    <style id="core-block-supports-duotone-inline-css">
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
+      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
+        filter: url(#wp-duotone-f6cff4-ffee58-1);
+      }
+
+      /*# sourceURL=core-block-supports-duotone-inline-css */
+    </style>
     <script
       src="http://localhost:8000/wp-includes/js/jquery/jquery.js?ver=3.7.1"
       id="jquery-core-js"
@@ -3495,50 +3653,6 @@
       </defs>
     </svg>
 
-    <style id="core-block-supports-inline-css">
-      /**
- * Core styles: block-supports
- */
-      .wp-container-core-group-is-layout-1c1b4f74 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--50) * -1);
-        margin-left: calc(var(--wp--preset--spacing--50) * -1);
-      }
-      .wp-container-core-columns-is-layout-9d6595d7 {
-        flex-wrap: nowrap;
-      }
-      .wp-elements-6c33bc3c49cd227fd8339cc6d69a7265
-        a:where(:not(.wp-element-button)) {
-        color: var(--wp--preset--color--base);
-      }
-      .wp-container-core-group-is-layout-45f4d935 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--60) * -1);
-        margin-left: calc(var(--wp--preset--spacing--60) * -1);
-      }
-      .wp-container-core-group-is-layout-651e6f64 > .alignfull {
-        margin-right: calc(var(--wp--preset--spacing--30) * -1);
-        margin-left: calc(var(--wp--preset--spacing--30) * -1);
-      }
-      .wp-block-gallery.wp-block-gallery-2 {
-        --wp--style--unstable-gallery-gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-        gap: var(
-          --wp--style--gallery-gap-default,
-          var(--gallery-block--gutter-size, var(--wp--style--block-gap, 0.5em))
-        );
-      }
-
-      /*# sourceURL=core-block-supports-inline-css */
-    </style>
-    <style id="core-block-supports-duotone-inline-css">
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image img,
-      .wp-duotone-f6cff4-ffee58-1.wp-block-image .components-placeholder {
-        filter: url(#wp-duotone-f6cff4-ffee58-1);
-      }
-
-      /*# sourceURL=core-block-supports-duotone-inline-css */
-    </style>
     <script
       src="http://localhost:8000/wp-includes/js/wp-embed.js?ver=6.9-alpha-60093-src"
       id="wp-embed-js"

Side-by-side view with Diff Checker: https://www.diffchecker.com/tCVBWjnO/

@westonruter
Copy link
Member

In this last diff (#10288 (comment)), I do see that this CSS appears in a different order:

    <link
      rel="stylesheet"
      id="twentyfourteen-block-style-css"
      href="http://localhost:8000/wp-content/themes/twentyfourteen/css/blocks.css?ver=20250715"
      media="all"
    />
  • Before: It appears after wp-block-library-css.
  • After: It appears before the individual block-specific stylesheets enqueued instead of wp-block-library-css.

Difference in the cascade for an IMG in the Image block:

Before After
image image

@westonruter
Copy link
Member

With many thanks to @dmsnell, there is now a fix for the CSS cascade issue: 61d2fa9.

The issue is that the styles were being inserted after wp_print_styles() finished as opposed to inserting the styles immediately after the position where wp-block-library was printed.

Block styles not on demand Block styles on demand
image image

…into block_styles_on_demand_in_classic_themes
FILE: src/wp-includes/script-loader.php
--------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
--------------------------------------------------------------------------------
 3584 | ERROR | Closures / anonymous functions declared as static do not have
      |       | access to $this
      |       | (PHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundInStatic)
 3586 | ERROR | Closures / anonymous functions declared as static do not have
      |       | access to $this
      |       | (PHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundInStatic)
--------------------------------------------------------------------------------
*/
$placeholder = sprintf( '/*%s*/', uniqid( 'wp_late_styles_placeholder:' ) );

wp_add_inline_style( 'wp-block-library', $placeholder );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one gotcha here which I want to investigate in a follow-up. It could be that a site doesn't use blocks at all, and they have removed this hook:

add_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' );

In this case, the style won't be present to add a placeholder to. This is likely exceedingly rare and an edge case that I don't think blocks the initial merge of this. But I want to follow on testing on a sites using the Classic Editor exclusively.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up in Core-64150.

Fixed in #10417

pento pushed a commit that referenced this pull request Oct 21, 2025
…template enhancement output buffer.

* This applies in classic themes when a site has not opted out of the template enhancement buffer by filtering `wp_should_output_buffer_template_for_enhancement` off.
* Both `should_load_separate_core_block_assets` and `should_load_block_assets_on_demand` are filtered on, as otherwise they are only enabled by default in block themes.
* Any style enqueued after `wp_head` and printed via `print_late_styles()` will get hoisted up to be inserted right after the `wp-block-library` inline style in the `HEAD`.
* The result is a >10% benchmarked improvement in LCP for core classic themes due to a ~100KB reduction in the amount of CSS unconditionally being served with every page load.

Developed in #10288

Follow-up to [60936].

Props sjapaget, westonruter, peterwilsoncc, dmsnell, mindctrl.
See #43258.
Fixes #64099.


git-svn-id: https://develop.svn.wordpress.org/trunk@61008 602fd350-edb4-49c9-b593-d223f7449a82
@github-actions
Copy link

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 61008
GitHub commit: b5e4bd8

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions bot closed this Oct 21, 2025
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Oct 21, 2025
…template enhancement output buffer.

* This applies in classic themes when a site has not opted out of the template enhancement buffer by filtering `wp_should_output_buffer_template_for_enhancement` off.
* Both `should_load_separate_core_block_assets` and `should_load_block_assets_on_demand` are filtered on, as otherwise they are only enabled by default in block themes.
* Any style enqueued after `wp_head` and printed via `print_late_styles()` will get hoisted up to be inserted right after the `wp-block-library` inline style in the `HEAD`.
* The result is a >10% benchmarked improvement in LCP for core classic themes due to a ~100KB reduction in the amount of CSS unconditionally being served with every page load.

Developed in WordPress/wordpress-develop#10288

Follow-up to [60936].

Props sjapaget, westonruter, peterwilsoncc, dmsnell, mindctrl.
See #43258.
Fixes #64099.

Built from https://develop.svn.wordpress.org/trunk@61008


git-svn-id: http://core.svn.wordpress.org/trunk@60344 1a063a9b-81f0-0310-95a4-ce76da25c4cd
github-actions bot pushed a commit to gilzow/wordpress-performance that referenced this pull request Oct 21, 2025
…template enhancement output buffer.

* This applies in classic themes when a site has not opted out of the template enhancement buffer by filtering `wp_should_output_buffer_template_for_enhancement` off.
* Both `should_load_separate_core_block_assets` and `should_load_block_assets_on_demand` are filtered on, as otherwise they are only enabled by default in block themes.
* Any style enqueued after `wp_head` and printed via `print_late_styles()` will get hoisted up to be inserted right after the `wp-block-library` inline style in the `HEAD`.
* The result is a >10% benchmarked improvement in LCP for core classic themes due to a ~100KB reduction in the amount of CSS unconditionally being served with every page load.

Developed in WordPress/wordpress-develop#10288

Follow-up to [60936].

Props sjapaget, westonruter, peterwilsoncc, dmsnell, mindctrl.
See #43258.
Fixes #64099.

Built from https://develop.svn.wordpress.org/trunk@61008


git-svn-id: https://core.svn.wordpress.org/trunk@60344 1a063a9b-81f0-0310-95a4-ce76da25c4cd
add_action( 'enqueue_block_assets', 'wp_enqueue_classic_theme_styles' );
add_action( 'enqueue_block_assets', 'wp_enqueue_registered_block_scripts_and_styles' );
add_action( 'enqueue_block_assets', 'enqueue_block_styles_assets', 30 );
add_action( 'init', 'wp_load_classic_theme_block_styles_on_demand', 8 ); // Must happen before register_core_block_style_handles() at priority 9.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep going back and forth on this, but why unconditionally add the hook and conditionally abort early if no block theme is present? why not group some of these into a big if ( wp_is_block_theme() ) {} block which then only adds the actions and filters if they are necessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because at this point the theme hasn't been loaded, so we don't know whether it is a block theme or not. In this way it's similar to functions like:

  • wp_enable_block_templates() which runs at after_setup_theme.
  • _add_default_theme_supports() which also runs at after_setup_theme.
  • _wp_block_theme_register_classic_sidebars() which runs at widgets_init.

Each have a check up front to see whether they are a block theme or not, and then short-circuit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes complete sense. that wasn’t clear to me before but I should have guessed that.

/*
* While normally late styles are printed, there is a filter to disable prevent this, so this makes sure they are
* printed. Note that this filter was intended to control whether to print the styles queued too late for the HTML
* head. This filter was introduced in <https://core.trac.wordpress.org/ticket/9346>. However, with the template
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be turned into a DocBlock comment and use {@link https://core.trac.wordpress.org/ticket/9346 Core-9346} if we want.

or does this <URL> syntax already generate anchor elements in the HTML docs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm. Good question. Well, this isn't the typical spot for a DocBlock, is it? At least according to phpDocumentor:

image

The comment here is for an add_filter() function call, so this doesn't seem like a place that a DocBlock would be recognized/appropriate.

Aside: It's so hard for me to not write “DockBlock”!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it’s definitely non-standard, but I have noticed IDE’s rendering things differently based on having one or two stars in the opening of the comment.

here specifically I was thinking mostly about the Codex/docs since they extract something like a variable DocBlock for filters and actions. In this case I don’t know the answer and don’t have time today to try and get the docs system running to generate and examine their output.

// Anonymous subclass of WP_HTML_Tag_Processor which exposes underlying bookmark spans.
$processor = new class( $buffer ) extends WP_HTML_Tag_Processor {
public function get_span(): WP_HTML_Span {
$instance = $this; // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundOutsideClass -- It is inside an anonymous class.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am really disheartened at how frequently I see pollution in our codebase to make up for the deficiency of the tools we’re using. this isn’t even an ignore statement for some rule — it’s a workaround to the fact that PHPCS is unable to recognize the structure of this code.

can we not address this in some other way, even by disabling the rule unless it can avoid false negatives?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fortunately it looks like this can be removed very soon! I just saw that the the issue for this sniff has been closed: PHPCompatibility/PHPCompatibility#1481

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once PHPCompatibility v10 is out we can remove this comment, and just use $this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not disable the rule until it’s reliable and not giving reliable false-positives? cc: @rodrigoprimo is this something you could help with? to disable the rule and remove the offending ignore statements until PHPCS doesn't get it wrong 100% of the time?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just remove this. I'm not seeing it being reported locally anymore for some reason.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the ping, @dmsnell! This is the kind of thing I can indeed help with. Feel free to reach out to me if you come across similar situations in the future.

to disable the rule and remove the offending ignore statements until PHPCS doesn't get it wrong 100% of the time?

I'm afraid I don't have permission to disable a PHPCS rule in this repository. Correct me if I'm wrong, but my understanding is that this is up to core committers.

That being said, I did check the PHPCompatibility issue and corresponding PR that @westonruter mentioned, and it does indeed fix the bug that is causing this false positive. I can open a Trac ticket to update PHPCompatibilityWP (and thus PHPCompatibility) once a new version is available, which should happen soon. In the same ticket, I can then remove the // phpcs:ignore comment.

Let me know if there is something else I can do here.

I'll just remove this. I'm not seeing it being reported locally anymore for some reason.

@westonruter, any chance are you running composer lint instead of composer compat? Only the latter checks for PHPCompatibility violations. I do see the PHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundOutsideClass error reported in my local environment if I remove the // phpcs:ignore comment and run composer compat.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigoprimo Ah, good catch. Yes, I was linting. If I run composer compat I do see the error:

PHP CODE SNIFFER REPORT SUMMARY
----------------------------------------------------------------------
FILE                                                  ERRORS  WARNINGS
----------------------------------------------------------------------
src/wp-includes/script-loader.php                     0       2
----------------------------------------------------------------------
A TOTAL OF 0 ERRORS AND 2 WARNINGS WERE FOUND IN 1 FILE
----------------------------------------------------------------------

Time: 9.66 secs; Memory: 10MB


PHP CODE SNIFFER VIOLATION SOURCE SUMMARY
---------------------------------------------------------------------------------
SOURCE                                                                      COUNT
---------------------------------------------------------------------------------
PHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundOutsideClass      2
---------------------------------------------------------------------------------
A TOTAL OF 2 SNIFF VIOLATIONS WERE FOUND IN 1 SOURCE
---------------------------------------------------------------------------------

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the exclusion in 92cd33c as part of #10436

};

// Loop over STYLE tags.
while ( $processor->next_tag( array( 'tag_name' => 'STYLE' ) ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, I see you write the full array form of the next_tag() query when it’s designed to support the more direct tag name argument. what about this form do you prefer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the explicitness of the array form. (And I forgot about being able to pass just a string too.)

}

// If the inline style lacks the placeholder comment, then something went wrong and we need to abort.
$css_text = $processor->get_modifiable_text();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve seen the need in my own code a few times to check for the presence of some pattern within the plaint text, but especially in the raw and undecoded plaintext. I think, for example, we would not want to match on CSS which matches the placeholder after being unescaped, e.g. \0077\0070-late-styles-placeholder…

maybe we need something like WP_HTML_Tag_Processor::matches_raw_and_undecoded_text() which can apply a PCRE pattern or basic string comparison to text nodes, SCRIPT and STYLE contents, and HTML comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the placeholder is a CSS comment and not inside of any CSS string literal where such Unicode escapes could trip it up, as I understand?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess here we’re guaranteed not to decode any CSS escapes, but if this were to become CSS-aware in the future, I could see this posing a problem.

the point you make is exactly what I’m saying. suppose we had some random CSS strings containing Unicode escapes, that when decoded, would produce something that looks like the placeholder. we wouldn’t want to match on that — only on a real honest-to-goodness raw string match.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, well, this shouldn't ever be possible because the placeholder includes a random string, so it shouldn't be possible for an existing stylesheet to somehow have the placeholder inside it already.

'Expected styles to be printed in the same order.'
);
$this->assertCount( 0, $found_styles['BODY'], 'Expected no styles to be present in the footer.' );
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test seems to capture the meat of what we want to assert, that the behaviors are applied. I think some of the other tests might be helpful in diagnosing why something might be broken, but they don’t seem to capture the same direct value this one does, like they are potentially asserting incidental details that serve the purpose of applying the behaviors in this test.

that may be a demonstration of my lack of understanding of the importance, say, of asserting whether the should_load_block_assets_on_demand has any hooked callbacks or not. I wonder though if these are as central to enforce as it is to examine whether the stylesheets have been hoisted or not.

could the assertions in those other tests change without breaking this feature? could this feature break even though those assertions hold? if so, they might represent a certain flakiness in the test suite due to indirect measurement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this... I'll open a new PR with more tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my long-winded comment was more questioning whether the additional tests already were falling more on the liability side than asset side — not at all meant to suggest adding more. 🙃

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think actually the tests were under-specified in terms of asserting the presence of the expected stylesheets in the HEAD and their specific ordering. I've opened #10436 to continue iterating on this.

westonruter added a commit to westonruter/wordpress-develop that referenced this pull request Oct 30, 2025
westonruter added a commit to westonruter/wordpress-develop that referenced this pull request Oct 30, 2025
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.

6 participants