Make WordPress Core


Ignore:
Timestamp:
07/07/2026 12:49:04 PM (2 months ago)
Author:
wildworks
Message:

Block Supports: Fix duplicate custom CSS for identical attributes.

wp_render_custom_css_support_styles() runs on every block render, and wp_unique_id_from_values() derives the class name from the block's attributes. Blocks with identical attributes therefore share the same processed CSS, which wp_add_inline_style() re-enqueued on each render, emitting the same rule once per occurrence.

Before enqueuing, skip the CSS if it is already present in the wp-block-custom-css handle's after inline styles`.

Developed in: https://github.com/WordPress/wordpress-develop/pull/11859.

Props masteradhoc, mukesh27, mustafabharmal, westonruter, wildworks.
Fixes #65268.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/block-supports/wpRenderCustomCssSupportStyles.php

    r61678 r62656  
    1515                parent::set_up();
    1616                $this->test_block_name = null;
     17
     18                global $wp_styles;
     19                $wp_styles = null;
    1720        }
    1821
     
    2225                }
    2326                $this->test_block_name = null;
     27
     28                global $wp_styles;
     29                $wp_styles = null;
     30
    2431                parent::tear_down();
    2532        }
     
    265272                );
    266273        }
     274
     275        /**
     276         * Tests that CSS is enqueued only once when the same block is rendered
     277         * multiple times, as happens inside a Query Loop.
     278         *
     279         * @ticket 65268
     280         *
     281         * @covers ::wp_render_custom_css_support_styles
     282         */
     283        public function test_css_not_duplicated_on_repeated_renders(): void {
     284                $this->test_block_name = 'test/custom-css-query-loop-dedup';
     285                register_block_type(
     286                        $this->test_block_name,
     287                        array(
     288                                'api_version' => 3,
     289                                'attributes'  => array(
     290                                        'style' => array(
     291                                                'type' => 'object',
     292                                        ),
     293                                ),
     294                                'supports'    => array( 'customCSS' => true ),
     295                        )
     296                );
     297
     298                $parsed_block = array(
     299                        'blockName' => 'test/custom-css-query-loop-dedup',
     300                        'attrs'     => array(
     301                                'style' => array(
     302                                        'css' => 'font-size: 2em; /* query-loop-dedup-test */',
     303                                ),
     304                        ),
     305                );
     306
     307                // Simulate the same block being rendered multiple times inside a Query Loop.
     308                $result = wp_render_custom_css_support_styles( $parsed_block );
     309                wp_render_custom_css_support_styles( $parsed_block );
     310                wp_render_custom_css_support_styles( $parsed_block );
     311
     312                // Extract the generated class name from the first render's result.
     313                $this->assertSame( 1, preg_match( '/(?:^|\s)(wp-custom-css-\S+)/', $result['attrs']['className'] ?? '', $matches ) );
     314                $class_name = $matches[1];
     315
     316                // Count how many times the CSS selector for this block appears in the enqueued inline styles.
     317                $inline_styles = (array) wp_styles()->get_data( 'wp-block-custom-css', 'after' );
     318                $occurrences   = 0;
     319                foreach ( $inline_styles as $style ) {
     320                        $this->assertIsString( $style );
     321                        $occurrences += substr_count( $style, '.' . $class_name );
     322                }
     323
     324                $this->assertSame(
     325                        1,
     326                        $occurrences,
     327                        'CSS should be enqueued exactly once even when the same block renders multiple times.'
     328                );
     329        }
    267330}
Note: See TracChangeset for help on using the changeset viewer.