Learn
How to Set Up a CDN: Step-by-Step Guide for Software Teams
How to set up a CDN for a software product comes down to six changes: a dedicated origin hostname, a CDN zone that ...
Native lazy loading defers an off-screen image or iframe until the user scrolls near it. For lazy loading images, the rule that holds up in production is to lazy load everything below the first viewport and never the Largest Contentful Paint (LCP) element. Applied to a hero image, loading="lazy" typically adds 300 to 500 ms to LCP, because the fetch cannot start until the browser has finished layout.
Since a 2020 change, Chromium-based browsers start fetching an image marked loading="lazy" once it is within 1,250 pixels of the viewport on fast connections and 2,500 pixels on 3G or slower. Firefox and Safari use their own, tighter margins, so the same page requests below-the-fold images at different scroll depths in each engine.
The attribute is a hint with one precondition: the browser has to know where the element sits relative to the viewport. That information only exists after style and layout, and layout usually waits for render-blocking CSS. An eager image found by the preload scanner can be requested within milliseconds of the HTML arriving. A lazy image is registered with an internal intersection observer and requested only when its box crosses the engine's distance threshold.
Three implementation details matter in practice:
loading="lazy" on iframes is supported in all major engines as of early 2024. The savings per element are usually much larger than for images. A typical third-party video or map embed pulls several hundred kilobytes of script plus its own connections, and a lazy iframe defers all of it. A facade (a static thumbnail that swaps in the real embed on click) defers it further, at the cost of one extra interaction before playback starts.
Lazy loading hurts LCP whenever the LCP element is a lazy image. The request is held until layout completes, so the time between Time to First Byte (TTFB) and the image request, which Chrome reports as "resource load delay", grows by however long render-blocking CSS and layout take. That is often 200 to 600 ms on mobile.
The worked example below uses round numbers. It is illustrative arithmetic, not a measurement:
This mistake is common. Public crawl data from 2021 to 2024 has repeatedly put the share of mobile pages that lazy load their own LCP image at roughly 10 to 18 percent. The usual causes are CMS defaults and templates that apply the attribute to every image in the content.
| Element position | loading | fetchpriority | Reason |
|---|---|---|---|
| LCP candidate (hero, product shot) | eager (omit the attribute) | high | Removes the 200 to 600 ms layout wait and jumps the request queue |
| Other images in the first viewport | eager | auto | Visible on load anyway; lazy only adds latency |
| Within about 1 screen below the fold | lazy | auto | Fetched almost immediately in Chromium, but stays off the critical path |
| Deep content, comments, footers | lazy | low or auto | Largest byte savings for readers who never scroll |
| Third-party embeds (video, maps) | lazy iframe or facade | n/a | Defers hundreds of kilobytes of script and extra connections |
The position of the element in the first rendered viewport, not its position in the HTML, decides whether lazy loading helps or hurts.
Responsive layouts make the rule harder to apply. The third card in a grid can be above the fold on desktop and two screens down on mobile. Templates should mark the first N items eager per breakpoint, or simply the first two or three content images. Marking nothing eager and relying on the browser to sort it out is the version that fails.
A lazy loading placeholder fills the reserved box until the real image arrives. Its job is to stop layout shift and soften the blank flash during a fast scroll, without adding bytes or main-thread work. The box size comes from width and height attributes or CSS aspect-ratio. The placeholder only decides what fills that box.
Avoid any placeholder scheme that swaps the real URL in with script after page load. It hides the image from the preload scanner and from crawlers that do not scroll, and it duplicates what the native attribute already does.
Lazy loading decides when an image is fetched. An image CDN decides how many bytes that fetch costs. The two compound. A lazy image served at the wrong width still wastes bandwidth when it does load, and a perfectly sized eager image still competes with the hero.
The pattern that works, described attribute by attribute:
The byte math explains why both halves matter. Take an article page with 25 images averaging 80 KB, where a typical reader scrolls only far enough to trigger the first 12. With lazy loading, the other 13 images (about 1.04 MB) are never requested for that reader. At 5 million such views a month, that is about 5.2 TB of egress avoided. Correct widths from the CDN then shrink the 12 images that do load.
If your delivery layer is BlazingCDN, crop, resize, resizefit and resizefill run on the fly at no extra charge, so a whole width ladder can come from one master file. The BlazingCDN features for image delivery and origin shield describe how origin shield and request coalescing keep first requests for new variants off your origin.
In the Chrome DevTools Performance panel, open the LCP marker and check two things: the element's loading attribute, and the "resource load delay" subpart. Anything above about 100 ms on an image LCP is a lazy-loading or discovery problem. In real user monitoring, segment LCP by whether the attributed element carried loading="lazy". On the CDN side, confirm that variant URLs return a cache hit status and that format-negotiated responses carry Vary: Accept.
Long, image-heavy pages such as feeds, catalogs, galleries and documentation gain the most. On those pages, 50% or more of image bytes can sit below the median scroll depth. Single-screen landing pages gain almost nothing and risk LCP regressions, so leave their images eager and spend the effort on fetchpriority and correct widths. Pages whose LCP element changes per breakpoint need per-breakpoint eager rules, not a global default.
Yes, when it is applied to the LCP image itself. A lazy image waits for render-blocking CSS and layout before its request starts, which commonly adds 200 to 600 ms of resource load delay on mobile. Below-the-fold images marked lazy do not hurt LCP, and they can help by freeing bandwidth for the hero image.
No. Images visible in the first viewport should load eagerly, and the LCP candidate should also carry fetchpriority=high. Lazy loading above-the-fold images saves no bytes, because they are fetched immediately anyway, and it adds a layout-dependent delay. On responsive sites, decide which images count as above the fold separately for each breakpoint.
A dominant-color background is the best default placeholder for lazy loading images. It costs a few bytes, needs no decode and no JavaScript. Blurred low-quality placeholders of 200 to 600 bytes look better, and Chrome has excluded such low-entropy images from LCP since 2023. Hash-based placeholders suit client-rendered apps that can afford the decode step.
Yes, Google indexes images that use native loading="lazy", because its renderer handles the attribute. Problems arise with script-based lazy loading that keeps the real URL out of the src or srcset attributes until a scroll event fires. A crawler that does not scroll may never see those images, so prefer the native attribute.
Yes. As of early 2024, all major browser engines support loading="lazy" on iframes. It is often the larger win, because video and map embeds pull several hundred kilobytes of script and open extra connections. For heavy embeds, a click-to-load facade defers even more, at the cost of one extra interaction before playback.
Pull a week of field LCP data and split it by template and by whether the LCP element carried loading="lazy". For every template where it did, remove the attribute, add fetchpriority=high, and compare p75 LCP a week later. Then sample 100 image requests from your CDN logs and check how often the delivered width exceeds the rendered width by more than 1.5 times. That ratio is the bandwidth a width ladder would recover.
If you want those variants generated at the edge, the BlazingCDN on-the-fly image processing page documents the included crop and resize operations, so you can try a width ladder against your own images.
Heavy traffic.
Light bill.
The CDN for video and large traffic
Learn
How to set up a CDN for a software product comes down to six changes: a dedicated origin hostname, a CDN zone that ...
Learn
To set up a CDN for static files, you need five things working together: a cacheable origin, a dedicated hostname ...
Learn
A video CDN is a content delivery network built for segmented HTTP streaming. It caches HLS and MPEG-DASH manifests and ...
Learn
CDN vs CMS is not a choice between two products. A content management system creates, stores and renders pages; a ...