Make imagify webp work with generateblocks image block

On one of my websites I had a problem with the query loop block from generateblocks with imagify. When using the <picture> tag to display webp images, the styling in the image block was not preserved. No matter what size or option I set in the image block in gutenberg, on the frontend the images did not show as I set them up.

Not all images come in the same dimensions. Thankfully there is tools available for us in GenerateBlocks to make them look the same on the frontend anyway.

Not all images are the same format. I can force the height for the frontend though. Or can I?

But when the imagify plugin is installed and active with the <picture> tag the image settings are completely ignored on the frontend.

Height setting is ignored on the frontend when imagify is active

What is happening?

GenerateBlocks stores its block specific styles in classes. For the image block these classes always start with gb-image- and a unique block identifier. So our css image height is for example stored in gb-image-644b6864.

When we have a look at the source of the website, we can see that the gb-image class is not added to the <img> tag. Imagify just removes any classes from the img tag. So how can we avoid that? It took some time to dig through the imagify code, but it was well worth it. Imagify does provide some filters we can hook into to make this work. The filter we are interested in is imagify_picture_img_attributes.

When generating its <picture> tags, imagify reads all <img> tags on the website first and then creates the picture tags with the info it finds in there. Before the picture tags are generated, all existing attributes are purged from the new element. This means our image styles from generateblocks, that are applied via css classes, are lost.

// imagify/classes/Webp/Picture/Display.php:326
protected function build_img_tag( $image ) {
	/**
	 * Gutenberg fix.
	 * Check for the 'wp-block-cover__image-background' class on the original image, and leave that class and style attributes if found.
	 */
	if ( ! empty( $image['attributes']['class'] ) && strpos( $image['attributes']['class'], 'wp-block-cover__image-background' ) !== false ) {
		$to_remove = [
			'id'     => '',
			'title'  => '',
		];
		$attributes = array_diff_key( $image['attributes'], $to_remove );
	} else {
		$to_remove = [
			'class'  => '',
			'id'     => '',
			'style'  => '',
			'title'  => '',
		];
		$attributes = array_diff_key( $image['attributes'], $to_remove );
	}
  	/**
	 * Filter the attributes to be added to the <img> tag.
	 *
	 * @since  1.9
	 * @author Grégory Viguier
	 *
	 * @param array $attributes A list of attributes to be added to the <img> tag.
	 * @param array $data       Data built from the originale <img> tag. See $this->process_image().
	 */
	$attributes = apply_filters( 'imagify_picture_img_attributes', $attributes, $image );

	return '<img' . $this->build_attributes( $attributes ) . "/>\n";
}

When looking at the code, we immediately see a possible vector to preserve our generateblocks class attribute. Before the image tag is built, a filter is run: imagify_picture_img_attributes that passes the original image through. In the original image element, our gb-image- class is still available.

So we can write a filter, that checks the image element for gb-image- classes, and add it back to the attributes. One way to do that would be like this:

add_filter('imagify_picture_img_attributes', 'fix_missing_gb_image_classes_imagify', 10, 2);
function fix_missing_gb_image_classes_imagify($attributes, $image) {
    if( isset($image['attributes']) && isset($image['attributes']['class']) ) {
        if( str_contains( $image['attributes']['class'], 'gb-image-' )) {
            preg_match('/gb-image-.+/', $image['attributes']['class'], $matches);
            $attributes['class'] = $attributes['class'] . ' ' . $matches[0];
        }
    }
    return $attributes;
}

All we do here is check the image element, if it contains a gb-image class, and then extract the exact class name via a simple regular expression. We then add the extracted class name back to the attributes array and return that. Now we can use generateblocks image styles in the query loop with imagify:

Our image styles are preserved. The gb-image class has been added to the image element

Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *