2026年11月12日
2026年11月12日
WordPress Responsive Images: srcset, sizes, Lazy Loading and WebP
This article is a localized edition of the Japanese original. Read the Japanese original
When you upload an image, WordPress creates several resized copies at the configured sizes. When a theme outputs images with wp_get_attachment_image() or through the block editor's Image block, srcset and sizes are added automatically, and the browser picks and loads an image that fits the screen.
If phones still load large images, or PageSpeed Insights flags image sizes, the resized copies usually do not match your layout or sizes differs from the actual display width. The contents of this article were checked against the source code of WordPress 6.9 as of November 2026 (wp-includes/media.php).
Attributes WordPress adds automatically
An <img> output by wp_get_attachment_image(), the_post_thumbnail() or an Image block in post content automatically gets the following attributes.
| Attribute | What it holds | When it is added |
|---|---|---|
srcset |
A list of resized copies with the same aspect ratio | When resized copies exist |
sizes |
A hint for the display width (default (max-width: image-width px) 100vw, image-width px) |
When srcset is added |
loading="lazy" |
Lazy loading | On images other than those judged to be in the first view |
fetchpriority="high" |
Load with high priority (WordPress 6.3 and later) | On one image: the first large image on the page (width × height of 50,000 pixels or more) |
decoding="async" |
Defer decoding of the image | On essentially every image |
sizes="auto, …" |
Lets the browser use the actual display width for lazy-loaded images (WordPress 6.7 and later) | On images with loading="lazy" and a width attribute |
In other words, if your theme outputs images with WordPress functions instead of hand-writing <img src="…">, most of the optimization is already done.
Deciding the sizes of resized images
Change the three standard sizes under Settings → Media
"Thumbnail size," "Medium size" and "Large size" can be changed under Settings → Media in the admin screen. Do not call update_option() in the theme's functions.php on every load to rewrite them, because that overrides the site administrator's settings.
Adding theme-specific sizes
Add sizes that match the theme layout with add_image_size().
<?php
add_action( 'after_setup_theme', function () {
// Enable featured images
add_theme_support( 'post-thumbnails' );
// name, width, height, crop
add_image_size( 'hero', 1920, 800, true ); // Crop to 1920×800
add_image_size( 'card', 600, 400, true ); // Crop to 600×400
} );
// Add them to the "Resolution" choices of the Image block and elsewhere
add_filter( 'image_size_names_choose', function ( $sizes ) {
return array_merge( $sizes, array(
'hero' => 'Hero image (1920×800)',
'card' => 'Card image (600×400)',
) );
} );
Only resized copies with the same aspect ratio as the image being shown go into srcset. A size whose aspect ratio changes through cropping (true) is treated as an image with a different aspect ratio. For example, when you show card (3:2), only 3:2 copies are listed in srcset. If you also want a smaller version for mobile, add a smaller size with the same aspect ratio (such as card-small at 300×200).
See the article on add_image_size for detailed steps on adding sizes.
Added sizes are created only for images uploaded afterwards
To create the new sizes for existing images, regenerate the resized copies.
- With a plugin, "Regenerate Thumbnails," distributed on wordpress.org, can regenerate them in bulk from "Tools."
- On a server with WP-CLI, you can regenerate them with this command.
# Create only the missing sizes
wp media regenerate --only-missing
With many images this takes time and uses more disk space, so take a backup before running it.
Outputting images in a theme
<?php
// Show the featured image at the card size (srcset, sizes, loading and so on are automatic)
echo wp_get_attachment_image(
get_post_thumbnail_id(),
'card',
false,
array(
'class' => 'card-image',
// Full screen width at 768px and below; about 360px in three columns on wider screens
'sizes' => '(max-width: 768px) 100vw, 360px',
)
);
sizes tells the browser how many pixels wide the image is displayed on screen. The default is based on the image width, so where an image is displayed narrower than its width, as in a card, writing it to match your layout as above keeps the browser from choosing an unnecessarily large image.
Large images in the first view
A hero image visible right after the page opens is likely to be the LCP (Largest Contentful Paint) element in PageSpeed Insights. WordPress automatically adds fetchpriority="high" to the first large image and removes lazy loading, but depending on how the theme is built, that detection can miss. In that case, set it explicitly.
<?php
echo wp_get_attachment_image(
get_post_thumbnail_id(),
'hero',
false,
array(
'loading' => false, // Do not add a loading attribute (no lazy loading)
'fetchpriority' => 'high', // Load with high priority
'sizes' => '100vw',
)
);
Setting loading to false omits the attribute entirely. If you give the same image both loading="lazy" and fetchpriority="high", WordPress issues a warning.
Adjusting sizes site-wide
To change sizes for content images all at once, use the wp_calculate_image_sizes filter. This example is for a theme whose content is at most 760px wide.
<?php
add_filter( 'wp_calculate_image_sizes', function ( $sizes, $size ) {
// $size is array( width, height )
$width = (int) $size[0];
// Images larger than the content width are displayed at the content width
if ( $width >= 760 ) {
return '(max-width: 800px) calc(100vw - 2rem), 760px';
}
return $sizes; // Leave smaller images at the default
}, 10, 2 );
From WordPress 6.7 on, auto is added to the start of sizes for lazy-loaded images, and browsers that support it choose the image by actual display width. So this filter matters most for first-view images that are not lazy-loaded and for browsers that do not support auto.
Creating resized images as WebP
WordPress has supported WebP uploads since 5.8, so code that adds WebP to upload_mimes is not needed.
To have resized copies created as WebP when you upload a JPEG, use the image_editor_output_format filter (WordPress 5.8 and later).
<?php
add_filter( 'image_editor_output_format', function ( $formats ) {
$formats['image/jpeg'] = 'image/webp'; // Save JPEG resized images as WebP
return $formats;
} );
- What changes are the images created from uploads made after you add this setting (resized copies and so on). The uploaded original file and existing images do not change.
- Your server's GD or Imagick must support WebP. Under Tools → Site Health, the media section of the "Info" tab shows which image library is in use and which formats it supports.
- With WebP, some environments that use the image files directly elsewhere (such as email newsletters) may still be unable to display them.
You may find examples online that use a filter called wp_upload_image_mime_transforms to create both JPEG and WebP, but that was a feature in the WordPress 6.1 development version and did not make it into the release. It does not exist in current WordPress. If you also want to convert existing images to WebP in bulk, consider an image optimization plugin such as EWWW Image Optimizer.
Checking
- On the front end, right-click an image, choose "Inspect" and check that the
<img>hassrcset,sizesandloading. - In the "Network" tab of the developer tools, filter by "Img," switch to a phone width, reload and check that smaller files are loaded.
- In PageSpeed Insights, check that the LCP image is not lazy-loaded.
Summary
- Output images with
wp_get_attachment_image()and similar functions instead of hand-writing<img>, andsrcset,sizes,loading,fetchpriorityanddecodingare added automatically. - Add theme-specific sizes with
add_image_size(); existing images need their resized copies regenerated. Only images with the same aspect ratio go intosrcset. - Where the display width differs from the image width, write
sizesto match your layout. - To make resized images WebP, use the
image_editor_output_formatfilter.
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)