Skip to content

wp_render_duotone_support() in > 5.9 prevents duotone filters being applied when loading page content with ajax. #39054

@slr1979

Description

@slr1979

Description

I am using a 3rd party theme which uses ajax/pjax page reloading. On upgrading from 5.8.3 to 5.9 and 5.9.1, I noticed that my images with duotone filters were no longer been applied when refreshing of content via ajax/pjax.

The wp_render_duotone_support() filter in > 5.9 does not allow any scope for use cases such as these and does not allow theme developers to control how/where the styles etc. are placed. The function assumes that a theme will being using hard pages reloads for every page. It would be great to find a solution that allowed more control over the placement of the Duotone styles etc. especially in the frontend. At this time I will be forced to use the solution below , stay on 5.8.3 or abandon the use of Duotone. Not ideal.

Step-by-step reproduction instructions

  1. Reload page content/main container using pjax/ajax on 5.8.3 - Duotone filters are successfully applied as relevant styles/filters/svg are within the main container which is reloaded via ajax/pjax.
  2. Reload page content/main container using pjax/ajax on > 5.9. - Duotone filters are not applied as relevant styles/filters/svg are placed in wp_footer which obviously does not get updated when reloading the main container using ajax/pjax .

Screenshots, screen recording, code snippet

So far, the only solution I have been able to find is to remove the wp_render_duotone_support() filter within my theme and replace it with a copy of the function from 5.8.3. I am unsure of the effect this may have on the block editor but it does not appear to cause any issues so far. As per other reports I am also forced to remove global styles and svg filters as they cause layout conflicts with the theme styles.

global $wp_version;
if ( version_compare( $wp_version, '5.9', '>=' ) ) {
	function remove_global_css() {
		remove_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles' );
		remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
		remove_filter( 'render_block', 'wp_render_duotone_support', 10, 2 );
	}
	add_action('init', 'remove_global_css');

	function wp_render_duotone_support_58( $block_content, $block ) {
		$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );

		$duotone_support = false;
		if ( $block_type && property_exists( $block_type, 'supports' ) ) {
			$duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
		}

		$has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] );

		if (
			! $duotone_support ||
			! $has_duotone_attribute
		) {
			return $block_content;
		}

		$duotone_colors = $block['attrs']['style']['color']['duotone'];

		$duotone_values = array(
			'r' => array(),
			'g' => array(),
			'b' => array(),
		);
		foreach ( $duotone_colors as $color_str ) {
			$color = wp_tinycolor_string_to_rgb( $color_str );

			$duotone_values['r'][] = $color['r'] / 255;
			$duotone_values['g'][] = $color['g'] / 255;
			$duotone_values['b'][] = $color['b'] / 255;
		}

		$duotone_id = 'wp-duotone-filter-' . uniqid();

		$selectors        = explode( ',', $duotone_support );
		$selectors_scoped = array_map(
			function ( $selector ) use ( $duotone_id ) {
				return '.' . $duotone_id . ' ' . trim( $selector );
			},
			$selectors
		);
		$selectors_group  = implode( ', ', $selectors_scoped );

		ob_start();

		?>

		<style>
			<?php echo $selectors_group; ?> {
				filter: url( <?php echo esc_url( '#' . $duotone_id ); ?> );
			}
		</style>

		<svg
			xmlns:xlink="http://www.w3.org/1999/xlink"
			viewBox="0 0 0 0"
			width="0"
			height="0"
			focusable="false"
			role="none"
			style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;"
		>
			<defs>
				<filter id="<?php echo esc_attr( $duotone_id ); ?>">
					<feColorMatrix
						type="matrix"
						<?php // phpcs:disable Generic.WhiteSpace.DisallowSpaceIndent ?>
						values=".299 .587 .114 0 0
								.299 .587 .114 0 0
								.299 .587 .114 0 0
								0 0 0 1 0"
						<?php // phpcs:enable Generic.WhiteSpace.DisallowSpaceIndent ?>
					/>
					<feComponentTransfer color-interpolation-filters="sRGB" >
						<feFuncR type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['r'] ) ); ?>" />
						<feFuncG type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['g'] ) ); ?>" />
						<feFuncB type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['b'] ) ); ?>" />
					</feComponentTransfer>
				</filter>
			</defs>
		</svg>

		<?php

		$duotone = ob_get_clean();

		// Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
		$content = preg_replace(
			'/' . preg_quote( 'class="', '/' ) . '/',
			'class="' . $duotone_id . ' ',
			$block_content,
			1
		);

		return $content . $duotone;
	}
	add_filter( 'render_block', 'wp_render_duotone_support_58', 10, 2 );
}

Environment info

WP 5.8.3 and WP 5.9.1, with Waveme (Flatfull)
All Browsers
Desktop with WIndows 10

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    CSS StylingRelated to editor and front end styles, CSS-specific issues.[Feature] ThemesQuestions or issues with incorporating or styling blocks in a theme.[Type] BugAn existing feature does not function as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions