“Widely supported” isn’t the same thing as “universally supported,” so it’s best to consider incorporating fallback options for browsers with limited AVIF support.
How to Use Next-Gen Image Formats With WordPress
The first step in using any next-gen image format is getting WordPress to recognize that it is an image. This can be accomplished by adding in some code snippets, either in a child theme’s functions.php
file or by including it in a customization plugin.
WordPress uses MIME types to determine which files can be uploaded to the Media Library and used in posts. If the file’s MIME type is not in the list, WordPress will not allow it to be uploaded.
The snippet below adds a filter to the WordPress upload_mimes
hook , which is used to validate the MIME type and extensions of uploaded files.
// Add AVIF image support to WordPress
add_filter( 'upload_mimes', 'filter_allowed_mimes_avif', 1000, 1 );
function filter_allowed_mimes_avif( $mime_types ) {
$mime_types['avif'] = 'image/avif';
return $mime_types;
}
This isn’t specific to AVIF files. The code above should allow you to add any next-gen image format to WordPress by swapping out all instances of avif
for the new MIME type’s file extension.
WordPress should recognize AVIF files as valid Media Library uploads at this point. You can even use them in posts and pages, but you’ll be limited to using them at full size…and WordPress won’t be able to tell you what the dimensions actually are. This is because WordPress uses the PHP getimagesize()
function to read image dimensions so it can generate metadata for the image, but PHP versions prior to 8.2 don’t return the right dimensions for AVIF images. Click Edit Image in the Media Library, and you can see that WordPress doesn’t seem to know anything about it.
Getting Correct Dimensions for Next-Gen Images
Now that WordPress recognizes the file format, the next step is getting it to acknowledge the image’s dimensions. The snippet below uses the imagecreatefromavif
function to create an image resource from the AVIF file, and then uses the imagesx
and imagesy
functions to get the width and height of the image. We then destroy the image resource using imagedestroy
, and return the generated metadata to WordPress.
// Get correct dimensions for AVIF images
add_filter( 'wp_generate_attachment_metadata', 'avif_image_metadata', 1, 3 );
function avif_image_metadata( $metadata, $attachment_id, $context ) {
if ( empty( $metadata ) ) {
return $metadata;
}
$attachment_post = get_post( $attachment_id );
if ( ! $attachment_post || is_wp_error( $attachment_post ) ) {
return $metadata;
}
if ( 'image/avif' !== $attachment_post->post_mime_type ) {
return $metadata;
}
if ( ( ! empty( $metadata['width'] ) && ( 0 !== $metadata['width'] ) ) && ( ! empty( $metadata['height'] ) && 0 !== $metadata['height'] ) ) {
return $metadata;
}
$file = get_attached_file( $attachment_id );
if ( ! $file ) {
return $metadata;
}
if ( empty( $metadata['width'] ) ) {
$metadata['width'] = 0;
}
if ( empty( $metadata['height'] ) ) {
$metadata['height'] = 0;
}
if ( empty( $metadata['file'] ) ) {
$metadata['file'] = _wp_relative_upload_path( $file );
}
if ( empty( $metadata['sizes'] ) ) {
$metadata['sizes'] = array();
}
// Create an image resource from the AVIF file
$image = imagecreatefromavif( $file );
// Get the width and height of the image
$metadata['width'] = imagesx( $image );
$metadata['height'] = imagesy( $image );
// Destroy the image resource
imagedestroy( $image );
return $metadata;
}
Click on Edit Image in the Media Library again, and you’ll see that WordPress can actually give us some information. Clicking on Scale will reveal the image’s dimensions, but something is still missing: the actual image!
WordPress automatically generates sub-sizes for image uploads, but that isn’t being done here. Using next-gen image formats like AVIF also requires that you register the new format with the WordPress sub-size image generation process and make sure the image is visible in the editor.
Generating Sub-Sizes for Next-Gen Image Formats
WordPress has all the required hooks for generating image sub-sizes. Adding some filters to these hooks will allow WordPress to automatically generate sub-sized versions of AVIF or other next-gen formats.
The code snippet below adds filters to the getimagesize_mimes_to_exts
hook, used to map image file extensions to their corresponding MIME types, the mime_types
hook, used to map MIME types to their corresponding file extensions, and the file_is_displayable_image
hook, used to determine whether an image file is displayable in the WordPress media library.
// Add AVIF image extension to WordPress
add_filter( 'getimagesize_mimes_to_exts', 'add_avif_file_extension', 1000, 1 );
function add_avif_file_extension( $mime_to_exts ) {
$mime_to_exts['image/avif'] = 'avif';
return $mime_to_exts;
}
// Add AVIF image type to WordPress
add_filter( 'mime_types', 'add_avif_mime_type', 1000, 1 );
function add_avif_mime_type( $mimes ) {
$mimes['avif'] = 'image/avif';
return $mimes;
}
// Display AVIF images
add_filter( 'file_is_displayable_image', 'is_avif_image_displayable', 1000, 2 );
function is_avif_image_displayable( $result, $path ) {
if ( str_ends_with( $path, '.avif' ) ) {
return true;
}
return $result;
}
Success! The image appears in the editor and WordPress generates sub-sized images as usual. Note that this will not create sub-sizes for AVIF images uploaded earlier, only new uploads.
Serving Fallback Images to Unsupported Browsers
The final step is to leverage the HTML <picture>
tag to conditionally display AVIF images based on browser capabilities.
The following code demonstrates how to implement conditional serving of AVIF images using the <picture>
tag:
<picture>
<source srcset="path/to/your/image.avif" type="image/avif"> <!-- specify path to AVIF image -->
<source srcset="path/to/your/fallback.jpg" type="image/jpeg"><!-- specify path to JPEG fallback image -->
<img src="path/to/your/default.png" alt="" /><!-- specify path to PNG default image -->
</picture>
The order of source elements matters. Browsers try to load sources until finding one that works. If no suitable source is found, the <img>
element loads the default image specified at the end.
Wrapping Up
At this point, you should be able to serve not only AVIF files, but any next-gen image formats the future brings us.
Are you already serving AVIF images to your users? Did you use a method like this, or a plugin? Let us know in the comments.