Native HTML Images and Lazy Loading
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
Baseline date: 2026-10-07. The browser already knows how to pick a file, delay a download and avoid layout jumps, if the markup gives it the information. This page lists the attributes that matter. The server side (which variants to produce and which URLs to return) is in responsive images and thumbnails, and the general loading-performance background is in performance and loading. Reference pages at MDN: image format guide and responsive images.
A complete example
<picture>
<source type="image/avif"
srcset="/covers/b81f/w320.avif 320w, /covers/b81f/w640.avif 640w, /covers/b81f/w1280.avif 1280w"
sizes="(min-width: 60em) 20vw, 50vw">
<source type="image/webp"
srcset="/covers/b81f/w320.webp 320w, /covers/b81f/w640.webp 640w, /covers/b81f/w1280.webp 1280w"
sizes="(min-width: 60em) 20vw, 50vw">
<img src="/covers/b81f/w640.jpg"
srcset="/covers/b81f/w320.jpg 320w, /covers/b81f/w640.jpg 640w, /covers/b81f/w1280.jpg 1280w"
sizes="(min-width: 60em) 20vw, 50vw"
width="640" height="960"
alt="Cover of Moby-Dick"
loading="lazy" decoding="async">
</picture>
The attributes
srcsetandsizes-
srcsetlists candidate files with their intrinsic width (640w) or pixel density (2x).sizestells the browser how wide the image will be on screen at each viewport width, so it can choose before layout. Withoutsizesthe browser assumes the image is as wide as the viewport and downloads too much. Use width descriptors for fluid layouts and density descriptors for fixed-size images such as avatars. widthandheight-
Give the intrinsic size. Browsers use the ratio to reserve space before the image loads, which prevents layout shift (CLS). Set the CSS to
height: auto; max-width: 100%so the image still scales. The same applies to<video>. <picture>andtype-
The browser takes the first
<source>whosetypeit supports, so list AVIF first, WebP second, and keep the<img>as the JPEG fallback. The<img>is required, since it is the element that is rendered, and every attribute that is not about source selection (alt,width,height,loading,decoding,fetchpriority) goes on it. loading="lazy"-
Defers offscreen images until they are near the viewport. It is supported natively by current browsers, with no JavaScript. Never put it on the image that is likely the largest contentful paint (LCP) element, usually the hero image or the first cover: lazy loading delays it and worsens LCP. Everything below the first screen should be lazy. Reference: MDN loading.
decoding="async"-
Lets the browser decode the image off the main thread and display other content first. It is safe on almost every image. Use
decoding="sync"only when you need the image painted in the same frame as the surrounding content. fetchpriority-
fetchpriority="high"on the LCP image tells the browser to fetch it ahead of other images.fetchpriority="low"on carousel slides and below-the-fold images helps bandwidth go to the right place. Use it sparingly: if everything is high, nothing is. Reference: MDN fetchpriority.
The LCP image
<img src="/hero/w1280.jpg" srcset="/hero/w640.jpg 640w, /hero/w1280.jpg 1280w, /hero/w1920.jpg 1920w"
sizes="100vw" width="1920" height="1080" alt="Library reading room"
fetchpriority="high" decoding="async">
The image has no loading="lazy" and has fetchpriority="high". To start the download even earlier, add a
<link rel="preload" as="image"> element to the head with the imagesrcset and imagesizes attributes.
A placeholder while the image loads
The width and height reserve an empty box. To fill it, show a BlurHash while the file downloads, see
BlurHash in the browser. A cheap CSS-only alternative is the
average colour of the image as background-color on the <img>, which the backend can return next to the BlurHash.
Video
<video controls playsinline preload="none" width="1280" height="720"
poster="/videos/42/poster-1280.avif">
<source src="/videos/42/720p.webm" type='video/webm; codecs="vp9, opus"'>
<source src="/videos/42/720p.mp4" type='video/mp4; codecs="avc1.64001f, mp4a.40.2"'>
Your browser cannot play this video.
</video>
-
posteris the image shown before playback. Generate it from a frame, see video covers and thumbnails, and serve it in the modern formats like any image (the attribute takes one URL, so choose AVIF or WebP only if you accept that older browsers show nothing, or keep a JPEG). -
preload="none"downloads nothing until the user presses play, which is right for lists of videos.preload="metadata"fetches the duration and dimensions only.preload="auto"lets the browser buffer, and wastes bandwidth when most visitors do not play. -
playsinlinekeeps playback inline on iOS rather than fullscreen. Addmutedfor autoplay, which browsers only allow for muted video. -
For several quality levels, use adaptive streaming rather than several
<source>files, see video playback and streaming.
A quick audit
-
Does every
<img>havewidth,heightandalt? -
Does every image below the first screen have
loading="lazy", and the LCP image does not? -
Does
sizesmatch the real CSS width of the slot? -
Do the
<picture>sources list AVIF and WebP with a JPEG fallback? -
Do the Lighthouse and Chrome DevTools Performance panels show the LCP element loaded early, and CLS near zero? See web.dev on LCP.