Skip to content

Instantly share code, notes, and snippets.

  • Star 41 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
How to easily generate low quality image placeholders (lqip) in WordPress

How to easily generate low quality image placeholders (lqip) in WordPress

I have made this function using the WP_Image_Editor class and I have filtered through the "wp_generate_attachment_metadata" hook. You can modify the "theme" namespace into function names with your theme name or in anyway you like.

Applying the filter directly to wp_generate_attachment_metadata the image placeholders are auto added into WordPress metadata, so when your add/modify/delete an image (or regenerate it via a plugin), it accomplishes to modify also to the image placeholders.

The use of the native theme support can prevent the generation of lqip or target specific image sizes to generate.

It contains an hook filter lqip_quality to modify the quality without have to modify the function.

This function could be modified and extended for example to differentiate quality for each size or apply filtering to a specific image size, etc.

Theme initialization

 * Your theme setup
function theme_setup() {
	// if you want to generate lqip for all the image sizes
	add_theme_support( 'lqip' );

	// if you want to specify what image sizes to generate lqip
	add_theme_support( 'lqip', array( 'thumbnail', 'medium' ) );
add_action( 'after_setup_theme', 'theme_setup' );

My simple function to make lqip

 * Easy adds lqip to WordPress
 * @global array $_wp_theme_features
 * @global array $_wp_additional_image_sizes
 * @param array $metadata
 * @param int $attachment_id
 * @return array $metadata
function theme_lqip_support( $metadata, $attachment_id ) {
	global $_wp_theme_features;

	if ( ! isset( $_wp_theme_features['lqip'] ) )
		return $metadata;

	global $_wp_additional_image_sizes;

	if ( is_array( $_wp_theme_features['lqip'] ) ) {
		$image_sizes = $_wp_theme_features['lqip'][0];
	} else {
		$image_sizes = get_intermediate_image_sizes();
		$image_sizes = apply_filters( 'intermediate_image_sizes_advanced', $image_sizes );

	$file = get_attached_file( $attachment_id );
	$quality = apply_filters( 'lqip_quality', 10 );

	if (
		preg_match( '!^image/!', get_post_mime_type( $attachment_id ) ) &&
		file_is_displayable_image( $file )
	) {
		$path_parts = pathinfo( $file );

		foreach ( $image_sizes as $size ) {
			if ( isset( $metadata['sizes'][$size] ) ) {
				if ( isset( $_wp_additional_image_sizes[$size]['width'] ) )
					$width = intval( $_wp_additional_image_sizes[$size]['width'] );
					$width = get_option( "{$size}_size_w" );

				if ( isset( $_wp_additional_image_sizes[$size]['height'] ) )
					$height = intval( $_wp_additional_image_sizes[$size]['height'] );
					$height = get_option( "{$size}_size_h" );

				if ( isset( $_wp_additional_image_sizes[$size]['crop'] ) )
					$crop = intval( $_wp_additional_image_sizes[$size]['crop'] );
					$crop = get_option( "{$size}_crop" );

				$new_size = $size . '-lqip';
				$filename = str_replace(
					'.' . $path_parts['extension'],
					'-lqip.' . $path_parts['extension'],
				$image = wp_get_image_editor( $file );
				$image->resize( $width, $height, $crop );
				$image->set_quality( $quality );
				$image->save( $path_parts['dirname'] . '/' . $filename );

				if ( ! is_wp_error( $image ) ) {
					$metadata['sizes'][$new_size] = $metadata['sizes'][$size];
					$metadata['sizes'][$new_size]['file'] = $filename;

	return $metadata;
add_filter( 'wp_generate_attachment_metadata', 'theme_lqip_support', 10, 2 );


To debug the filter during image upload or manipulation you can add this code in the function theme_lqip_support before the return or inside the foreach loop.

A fresh dump.txt file will be created in the same directory files where stored.

	file_put_contents( $path_parts['dirname'] . '/dump.txt', print_r(
			'_wp_theme_features' => $_wp_theme_features,
			'_wp_additional_image_sizes' => $_wp_additional_image_sizes,
			'image_sizes' => $image_sizes,
			'metadata' => $metadata,
			'attachment_id' => $attachment_id,
			'file' => $file,
			'quality' => $quality,
			'path_parts' => $path_parts,
			'image' => $image,
			'new_size' => $new_size,
			'filename' => $filename
	, true ) );

Feedbacks and suggestions will be appreciated :)

Tested up to: WordPress 4.0 License: MIT MIT License (Expat)

Copy link

Thank you for this. Really helpful inspiration.

Just two remarks:

  • the action hook to add the theme support is "after_setup_theme" not "after_theme_setup"
  • I would suggest adding the width and height of the newly created image to the metadata like this:
$metadata['sizes'][$new_size]['width'] = $width;
$metadata['sizes'][$new_size]['height'] = $height;

This way other plugins/functions depending on dimensions don't throw an error.

Copy link

Hey! Very nice solution! But, I wanted to generate the lqip version only for the original image instead of other sizes. How could I do this?

Copy link


really nice script, but if it works backward with existing media images for example with thumbnail regenerator?

Copy link

What should I be expecting to see when running this script? It appears that a new image will be created with -lqip added as a suffix, but I'm not seeing any new images created, period.

Copy link

Thank you very much, you are awesome :-)

Copy link

rsharrys commented Sep 9, 2021

How do I exclude the (lqip) format from the picture gallery? Currently it overwrites srcset medium size 300px -> 300px lqip.

<img width="768" height="512" src="http://site/image-768x512.jpg" class="attachment-medium_large size-medium_large wp-post-image lazyload" alt="" loading="lazy" sizes="(max-width: 768px) 100vw, 768px" srcset="http://site/image-768x512.jpg 768w, http://site/image-300x200-lqip.jpg 300w, http://site/image-1024x683.jpg 1024w, http://site/image-1536x1024.jpg 1536w, http://site/image.jpg 1600w">

Copy link

ctlcltd commented Sep 29, 2021

@rsharrys It's been a while since I wrote this script. Changes have been introduced in the meantime. You could try using this filter:

add_filter( 'wp_image_resize_identical_dimensions', '__return_true' );

otherwise you could modify the script to not allow images of that resolution to be overwritten.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment