Vyso Guides
WordPress image optimization: a practical workflow
To optimize images in WordPress, resize them for your layout, reduce file size without visible damage, and make sure each page loads the right version at the right time. Start with one representative page, then apply the same process to the rest of the Media Library.
WordPress image optimization: the short version
Resize images for their largest actual use. Keep enough resolution for sharp images on high-density screens, including any gallery zoom view.
Compress before or during upload. Compare the result at its intended display size, especially around small text and fine detail.
Use WebP or AVIF when they produce a smaller file at acceptable quality. Check that your upload and delivery setup supports the format.
Let WordPress generate smaller image sizes. Use a size suitable for the layout instead of selecting the largest available file by default.
Check responsive delivery. The
srcsetandsizesattributes help the browser choose a file for the screen; confirm that mobile visitors receive a suitable version.Lazy-load images farther down the page. If PageSpeed Insights identifies an image as the Largest Contentful Paint (LCP) element, exclude that image from lazy loading so the main visible content can appear promptly.
Optimize existing media too. Back up the uploads and database, then test a small batch before processing the library, including its smaller image copies.
Test the published page with PageSpeed Insights or browser developer tools. Clear affected caches and compare image downloads and loading on mobile and desktop.
Why image optimization matters
Oversized or poorly compressed images transfer unnecessary bytes. Visitors wait longer for content, especially on slower connections. Large files also use more bandwidth, while unnecessary image copies take up storage.
Image problems can affect Core Web Vitals: a slow main image can delay LCP, and images without reserved space can cause layout shifts. Compression alone does not fix either loading order or missing dimensions.
Google uses Core Web Vitals in its ranking systems, but good scores do not guarantee higher rankings. Image optimization improves the loading experience; it does not replace relevant content. Google's page experience guidance.
Choose how to optimize your images
The three main approaches differ in when the work happens: before upload, during WordPress processing, or when delivering an image to a visitor.
Manual optimization
Resize, compress, and convert images before uploading them. This gives you control over each export, but requires more work for every new image. It suits a small library or images that need individual quality checks.
WordPress then creates smaller copies for different uses. These native sizes help with responsive delivery, but the files and loading behavior still need checking.
WordPress optimization plugin
An image optimization plugin can automate processing of new uploads. Some also offer bulk processing for the existing Media Library.
Check whether your chosen tool processes the original, the generated sizes, or both. Test a few attachments before a bulk run. This approach reduces repeated upload work while keeping management in WordPress.
Image CDN or delivery service
A delivery service with image transformation features can resize, compress, crop, and convert images as they are requested. Format conversion depends on the service and configuration. Requested variants can be cached for reuse.
This becomes useful with large libraries, many layout variants, higher traffic, or teams publishing too many images to prepare each one manually. The delivery setup must still request suitable dimensions and preserve the page's loading behavior.
Once managing every upload, size, format, and delivery rule becomes impractical, automate those jobs through a defined workflow. Keep the same quality checks and LCP exclusion as you move from manual exports to plugin or delivery automation.
Choose dimensions and compression for the layout
An image displayed at 800 pixels wide in the page layout needs about 1600 image pixels for a 2× display. The layout measurement is its width in CSS pixels; a high-density screen uses more image pixels to keep it sharp. Provide smaller versions for smaller screens.
Keep enough resolution for the largest intended use, including crops and zoom views. A large upload does not necessarily reach visitors unchanged: responsive markup can direct the browser to a smaller file. The downloaded candidate is what determines transfer cost.
Compare JPEG, WebP, and AVIF exports at the intended display size. For photos, lower lossy quality until artifacts become visible, then increase it slightly. For screenshots with small text or diagrams, test lossless output too. Choose by visible quality and actual bytes; the same quality number means different things in different encoders. Keep a source copy so future exports do not repeatedly recompress an already degraded image.
Understand the files WordPress creates
One Media Library attachment can represent several files. These derivatives are smaller or cropped copies of the uploaded image. WordPress has thumbnail, medium, medium_large, and large sub-sizes. The thumbnail, medium, and large dimensions are adjustable in Settings → Media. The default medium_large width is 768 pixels. WordPress also registers 1536x1536 and 2048x2048 variants, which fit within those bounds while preserving proportions. These names do not mean every image becomes square.
full refers to the attachment's main image. In the standard server processing path, images exceeding the default threshold of 2560 pixels in either dimension receive a scaled version used as full; the uploaded original is retained. Filters can change this behavior.
Themes and plugins can register additional dimensions and crops through add_image_size(). A shop card, article header, and gallery may therefore use different derivatives of one attachment. Inventory the active sizes before changing them.
Extra derivatives consume storage and processing time. They do not all download simply because they exist. Remove a registered size only after checking where it is used; removing useful responsive candidates can make visitors download larger files.
Use WebP and AVIF with the right processing path
WordPress has supported WebP uploads since 5.8 and AVIF since 6.5. For server processing, the active GD or Imagick image editor needs support for the chosen format. Check Tools → Site Health → Info → Media Handling for supported formats.
WordPress 7.1 adds browser processing for supported block-editor uploads, including compression, resizing, and thumbnail generation. When that path is active, AVIF uploads can work even without server-side AVIF support. It currently depends on supported Chromium browsers and runtime checks; unavailable browser processing falls back to the server. Test uploads through the path your editors actually use.
For ordinary JPEG uploads, installing current WordPress does not automatically switch output to WebP or AVIF. Developers can configure native conversion with image_editor_output_format; plugins can configure it too. The filter also applies to the browser processing path. Existing files need separate processing.
Use the smaller format that preserves the image's detail. For older visitor browsers, a <picture> element can offer AVIF or WebP sources with a JPEG or PNG fallback. Test the delivery setup; server support and visitor browser support are separate checks.
Make responsive markup match the displayed width
WordPress can add srcset and sizes to recognized attachment images in content and to images rendered with wp_get_attachment_image(), through its responsive image functionality. Custom templates and page builders still need inspection. A CSS background or single-source image may need a separate responsive delivery setup.
srcset lists candidate files and their widths. sizes describes the intended display width. The browser uses these hints and display density to select a candidate. For an image displayed at 360 CSS pixels on a 2× screen, a candidate around 720 pixels wide is reasonable. A 768-pixel download is not automatically wasteful.
For a column capped at 800 pixels with 16-pixel margins on each side, a matching hint is:
sizes="(max-width: 832px)
calc(100vw - 32px), 800px"Adapt the value to the actual layout. WordPress's default fallback uses the requested image width and 100vw; it cannot describe every column layout accurately. A hint that overstates display width can cause an unnecessarily large download.
Since WordPress 6.7, eligible lazy-loaded images receive a sizes value starting with auto,. Supporting browsers use the rendered width; other browsers use the remaining fallback list. This is valid for lazy-loaded images. If a plugin later changes an image to eager loading, it must also remove the auto prefix.
WordPress selects responsive candidates with matching aspect ratios. A square card crop will not normally appear in a landscape image's srcset. If a candidate is missing, check the crop and attachment metadata before generating more files.
Keep the LCP image out of lazy loading
LCP measures when the largest eligible image or text block becomes visible. Identify that element separately on mobile and desktop; the featured image is not always the LCP element.
WordPress uses heuristics to omit lazy loading from likely in-viewport images and, since 6.3, to give a likely LCP image fetchpriority="high". These are predictions, so check the final HTML when a theme or performance plugin changes loading behavior.
Native loading="lazy" lets the browser defer a download until the image approaches the viewport; it can start before scrolling. Keep it for suitable images farther down the page. An image's width and height help reserve space before it loads and reduce layout shifts.
For the confirmed LCP image, remove lazy loading or use loading="eager", and keep a real src or srcset in the initial HTML. Give that image high fetch priority. For a custom PHP template whose featured image is the confirmed LCP image, using the 800-pixel column above:
echo wp_get_attachment_image(
get_post_thumbnail_id(),
'large',
false,
array(
'loading' => 'eager',
'fetchpriority' => 'high',
'sizes' =>
'(max-width: 832px)
calc(100vw - 32px), 800px',
)
);Adjust the size and sizes value for your template. The attachment API retains responsive image generation and accepts these loading overrides. WordPress warns against combining loading="lazy" with fetchpriority="high".
In a builder or optimization plugin, apply its lazy-loading exclusion to the specific image and verify the rendered result. Raising priority does not fix a URL hidden in data-src until JavaScript runs. Preload can help a late-discovered CSS background; for responsive images, match the preload's candidates to the displayed image to avoid duplicate downloads.
Optimize the existing Media Library
Start with images used on important pages. Back up the uploads and database before modifying existing media. In an optimizer's bulk or existing-media settings, check which files it processes and select a small sample containing photos, screenshots, and any transparent graphics you use. Include the derivatives those pages request. Compressing only the original leaves existing thumbnails untouched; a conversion setting for future uploads does not update an older post's files.
Choose bulk processing that preserves attachment references and keeps existing image URLs working. After the trial, check old posts, galleries, and any directly embedded URLs before processing the remaining library. If you use an image CDN, include its variants and caches in the check.
Inventory and regenerate image sizes
With WP-CLI installed, run this from the WordPress directory:
wp media image-sizeThe image-size command lists registered sizes, including theme and plugin sizes. Check which ones your layout uses before rebuilding files.
Separate two jobs: regenerating sizes creates image derivatives; bulk optimization compresses or converts the files selected by your tool. If a theme introduces a size that older attachments lack, regenerate the missing sizes. WordPress exposes a missing-size API, and WP-CLI provides regeneration commands.
To generate missing sizes for an example attachment with ID 123 while retaining old thumbnail files:
wp media regenerate 123 --only-missing --skip-deleteReplace 123 with an attachment ID from your site. --only-missing skips existing sizes, so it will not re-encode them after a quality change. To rebuild that attachment's existing sizes too, use:
wp media regenerate 123 --skip-deleteThe --skip-delete option retains old thumbnail files, which is useful when existing URLs are linked elsewhere. Regeneration runs on the server, so browser-based AVIF upload support alone does not establish that the server can regenerate those files.
Finish generating the required sizes before compressing them, unless your optimizer explicitly handles regeneration. Otherwise the regenerated files need another optimization pass.
For ongoing uploads, assign compression and format delivery to one configured system. Verify that it handles the sizes your site requests and keeps the LCP exclusion intact. Overlapping plugins make it harder to identify which system rewrote the markup or recompressed a file.
Validate the downloaded file and loading behavior
Start with a PageSpeed Insights test of the published URL. Compare mobile and desktop results and check whether the LCP element is an image. For the exact file and loading details, inspect the page in your browser.
Inspect the selected image in DevTools
Open the published page while logged out. Set the mobile viewport before reloading, then use Empty Cache and Hard Reload with DevTools open. Keep the same network conditions for before-and-after comparisons. Inspect image requests for transferred bytes, response type, and errors. A filename ending in .jpg can still be served through a format-converting service, so check the response's Content-Type.
Select an <img> in the Elements panel and run this in the Console. DevTools uses $0 for the selected element.
({
selectedFile: $0.currentSrc,
displayedWidth: $0.getBoundingClientRect().width,
devicePixelRatio: window.devicePixelRatio,
srcset: $0.getAttribute('srcset'),
sizes: $0.getAttribute('sizes'),
loading: $0.getAttribute('loading'),
fetchpriority: $0.getAttribute('fetchpriority')
})
currentSrc shows the candidate the browser selected. Compare its actual pixel dimensions with displayed width × device pixel ratio, then check its bytes in Network. Repeat at desktop width with a fresh reload.
Record a page-load trace in the Performance panel. Check the LCP element, when its request begins, and any layout shifts. Smaller files with unchanged LCP call for checking request discovery, server response time, and render delay in the LCP breakdown.
Distinguish a test result from real-user history
Use repeatable lab tests for immediate checks, then monitor real-user results. A good LCP is 2.5 seconds or less at the 75th percentile. PageSpeed Insights field data covers the previous 28 days and may fall back to site-wide origin data when the page lacks samples. A successful local test will not immediately replace that history.
Keep going
Make the media library less work.
See how Vyso brings search, enrichment, cleanup, and delivery into one product.
Start free