Why This Problem Happens
Carousel image paint lag is a common side effect when the WordPress 6 Gutenberg image block sits inside a slider or hero carousel and the browser treats the first visible image as non-critical. In practice, the lag usually comes from three overlapping issues: the first slide is lazy-loaded, the image does not get the right network priority, or the block markup does not reserve stable dimensions early enough.
WordPress core has improved image loading behavior over several releases. WordPress added native lazy loading in 5.5, then introduced centralized loading optimization logic in 6.3 through `wp_get_loading_optimization_attributes()`, which can assign `loading`, `decoding`, and `fetchpriority` based on context. That helps normal image output, but carousels are still a special case because the first visible slide can be misclassified while later slides should remain deferred. If your slider plugin, theme, or optimization layer rewrites the same image again, paint delay gets worse.
Quick Diagnosis Table
| Check | What To Look For | Why It Matters | Recommended Fix |
|---|---|---|---|
| First slide markup | `loading="lazy"` on the visible slide | Delays the image most likely to affect LCP | Set the first visible slide to eager loading |
| Network priority | No `fetchpriority="high"` on the lead image | Browser may prioritize CSS or other images first | Add `fetchpriority="high"` only to the first critical slide |
| Image dimensions | Missing `width` and `height` | Causes unstable layout and slower paint decisions | Output intrinsic dimensions on every carousel image |
| Duplicate lazy loading | `data-src`, placeholders, or plugin lazy classes | Multiple optimization layers can delay the same image twice | Disable lazy loading for the first slide in one layer only |
| Responsive sizing | Oversized source chosen on mobile | Extra transfer time slows rendering | Use correct `srcset` and `sizes` values |
What WordPress Core Already Does
WordPress core now uses `wp_get_loading_optimization_attributes()` to determine whether an image should get `loading="lazy"`, `fetchpriority="high"`, and `decoding="async"`. The WordPress 6.3 performance note explains that this change was made specifically to improve image-related load time behavior and avoid applying lazy loading to images that are likely in the viewport.
That is useful, but a carousel can still break the heuristic. A slider often hides non-active slides, duplicates slides for looping, or injects wrapper markup that makes the first visible image look like just another attachment image. WordPress also documents that `wp_get_attachment_image_attributes` can be filtered before output, which gives you a precise place to override only the carousel images that matter.
For broader context on image transfer costs, this Flux Plugins article on web image performance is worth reviewing because large image bytes and poor priority hints usually compound each other.
Fix Carousel Image Paint Lag in WordPress 6 Gutenberg
1. Eager-Load Only The First Visible Carousel Image
Google's web performance guidance is clear: images visible in the first viewport should not be lazy-loaded. The first visible carousel image is often the LCP candidate, so `loading="lazy"` is the wrong default there.
Keep lazy loading for later slides, but force the first visible slide to load eagerly. If your carousel is built with `wp_get_attachment_image()`, filter the attributes for a known class:
add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment, $size ) {
$class = $attr['class'] ?? '';
if ( strpos( $class, 'carousel-slide-image is-first-visible-slide' ) !== false ) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
}
return $attr;
}, 10, 3 );
This is the safest pattern because WordPress core explicitly warns that an image should not be both lazy-loaded and marked high priority at the same time.
2. Add Fetch Priority To The Lead Slide Only
WordPress 6.3 can automatically add `fetchpriority="high"` to the image it thinks is the LCP image, but carousels are one of the places where being explicit is often safer. MDN describes `fetchpriority` as a browser hint that can raise or lower the relative fetching priority of an image.
Use it sparingly. One lead slide is enough. If you mark every slide as high priority, you remove the benefit and increase resource contention.
3. Keep Width And Height On Every Image Block
WordPress has long tied image optimization to stable dimensions. Its lazy-loading notes explain that `width` and `height` help the browser reserve space before the image finishes loading. Web.dev makes the same point: dimensions reduce layout shifts and improve how the browser schedules rendering.
If your Gutenberg image block is converted by the theme into custom slider markup, make sure those intrinsic dimensions survive. A carousel image without dimensions may still load, but the browser has less information to paint it efficiently.
4. Remove Double Lazy Loading
A very common cause of carousel image paint lag is a second optimizer layer. Core adds native loading attributes, then a performance plugin or slider library adds `data-src`, placeholder GIFs, or JavaScript-based swapping on top.
Inspect the first slide in the rendered HTML. If you see a mix of native attributes and plugin-specific lazy attributes, pick one system. In most WordPress setups, the cleanest approach is:
- Keep native WordPress image markup
- Exclude the first carousel slide from plugin lazy loading
- Let later slides remain deferred
If you are troubleshooting a more general conflict, this related Flux Plugins guide on fixing lazy loading conflicts covers the same pattern from the plugin-conflict angle.
5. Fix Responsive Image Sizing
Even when the priority is correct, the first slide can still paint late if the browser selects an unnecessarily large image candidate. WordPress image output supports `srcset` and `sizes`, and that matters more inside a full-width Gutenberg carousel because desktop-sized assets are often sent to smaller screens.
Review the `sizes` attribute for your slider container. If the first slide never renders wider than the viewport, tell the browser that directly instead of leaving an overly broad default.
add_filter( 'wp_get_attachment_image_attributes', function( $attr ) {
$class = $attr['class'] ?? '';
if ( strpos( $class, 'carousel-slide-image' ) !== false ) {
$attr['sizes'] = '(max-width: 782px) 100vw, 1200px';
}
return $attr;
}, 10 );
Use real measurements from your theme, not copied values.
Recommended Configuration Matrix
| Carousel Element | Loading | Fetch Priority | Notes |
|---|---|---|---|
| First visible slide | `eager` | `high` | Most likely LCP image |
| Second and later slides | `lazy` | `auto` or omitted | Preserve bandwidth savings |
| Hidden loop clones | `lazy` or excluded from crawl importance | `low` or omitted | Do not compete with the visible slide |
| Thumbnail navigation images | `lazy` | omitted | Usually not critical for first paint |
Verification Steps
Check The Markup
View source, not just the live DOM. Confirm that the first visible carousel image ships in the initial HTML as an actual image element, not only as a CSS background or JavaScript-injected node.
Check Network Priority In DevTools
Open Chrome DevTools and reload the page. The lead carousel image should start early and show higher priority behavior than deferred slides.
Check Core Web Vitals Impact
Compare before and after in Lighthouse or WebPageTest. The most common win is a faster LCP and a more stable first render, especially on mobile.
Conclusion
The clean fix for carousel image paint lag caused by the WordPress 6 Gutenberg image block is not to disable all lazy loading. It is to treat the first visible slide as critical and everything else as deferrable. In practical terms, that means eager loading the lead image, adding `fetchpriority="high"` only there, preserving width and height, avoiding duplicate lazy-load systems, and tightening responsive sizing.
That approach matches WordPress core guidance, aligns with Google's advice to avoid lazy loading above-the-fold images, and keeps the performance benefits of deferred loading for the rest of the carousel.