Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You cannot defer an ordinary image request with CSS alone. Put the native HTML hint loading="lazy" on images that are initially offscreen, then use CSS for sizing and presentation. Keep the likely above-the-fold and Largest Contentful Paint (LCP) image eager, and always provide width and height so the browser can reserve its space.

Can CSS lazy-load an image?

CSS controls layout, appearance and rendering work. The documented browser control for deferring a normal <img> fetch is HTML’s loading attribute:

  • loading="lazy" asks the browser to delay fetching until conditions chosen by the user agent are met.
  • loading="eager" requests normal, immediate loading and is the default when the attribute is omitted.

CSS still matters: it keeps images responsive, establishes their aspect ratio and can reduce the work needed to render offscreen content. It does not replace the HTML loading hint.

The minimal no-JavaScript implementation

<img
  src="gallery-image.jpg"
  loading="eager"
  width="1200"
  height="800"
  alt="Describe the image's meaningful content"
>
img {
  max-width: 100%;
  height: auto;
}

The browser calculates how far an image may be from the viewport before it starts the request. That distance is user-agent controlled, so do not promise a fixed number of pixels or a universal loading moment.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose which images should be lazy

Lazy loading is a decision about visibility and importance, not a class to apply indiscriminately.

Image situation Recommended setting Reason
Hero, poster or other image visible in the initial viewport loading="eager" or omit the attribute It is likely to be needed immediately; delaying it can hurt the page’s LCP.
Image below the initial viewport in a long article or gallery loading="lazy" The browser can defer work until the reader approaches it.
Image whose visibility is uncertain but is part of the first screen at common viewport sizes Keep it eager Measure the design rather than assuming it is offscreen.

LCP and fetch priority are separate concerns

The fetchpriority hint is a separate control for relative fetch priority. Setting loading="eager" does not itself raise an image’s priority. Use an eager setting for a critical first-screen image, and treat priority as a separate performance decision supported by your page’s loading strategy.

Reserve the image’s space before it downloads

Declare the intrinsic dimensions with width and height. The browser can derive an aspect ratio and reserve that rectangle before the file arrives, which helps prevent content from jumping as the image appears. Lazy-loaded images without an established layout size can also fail to load when they never intersect a visible part of an element.

<figure class="card-image">
  <img
    src="mountain-trail.webp"
    loading="eager"
    width="1600"
    height="1067"
    alt="A trail winding through a mountain valley"
  >
  <figcaption>Mountain trail</figcaption>
</figure>
.card-image {
  margin: 0;
}

.card-image img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}

The CSS width can scale the image down for a narrow container while the declared dimensions preserve the correct ratio. Use the real ratio of the file, not a convenient placeholder pair.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A complete lazy-loaded gallery

This example leaves the first image eager because it appears first, and defers the later cards. No JavaScript observer or scroll handler is required.

<section class="gallery" aria-labelledby="gallery-title">
  <h2 id="gallery-title">Coastal walk</h2>

  <img
    class="gallery__hero"
    src="coast-hero.jpg"
    loading="eager"
    width="2000"
    height="1200"
    alt="Cliffs beside a calm blue bay"
  >

  <div class="gallery__grid">
    <img
      src="coast-01.jpg"
      loading="eager"
      width="1200"
      height="800"
      alt="Footpath above the shoreline"
    >
    <img
      src="coast-02.jpg"
      loading="eager"
      width="1200"
      height="800"
      alt="Sea birds on a rock"
    >
    <img
      src="coast-03.jpg"
      loading="eager"
      width="1200"
      height="800"
      alt="Sunlight on the water at low tide"
    >
  </div>
</section>
.gallery {
  max-width: 70rem;
  margin-inline: auto;
}

.gallery img {
  display: block;
  width: 100%;
  height: auto;
}

.gallery__hero {
  margin-block-end: 1rem;
}

.gallery__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
}

Keep meaningful alternative text even when the image is lazy. Loading behavior should not determine whether assistive technology receives an appropriate description.

What the browser actually defers

The HTML Standard describes the attribute as directing the user agent to fetch a resource immediately or defer fetching until conditions associated with the element are met. With lazy, the browser chooses those conditions and the fetch distance. Network speed, viewport size and implementation details can affect when the request begins.

Do not build correctness around an exact threshold. If an image must be available before interaction, keep it eager. If it is ordinary content below the fold, let the browser decide when to fetch it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

As context, a web.dev report cited HTTP Archive data showing that sites at the 90th percentile send more than 5 MB of images on both desktop and mobile. In Chrome-on-Android experiments reported there, 97.5% of lazy-loaded images finished within 10 ms of becoming visible on 4G, and 92.6% did so on slow 2G. Those are observations from that report, not guarantees for every browser, network or current site.

Where content-visibility fits

CSS content-visibility: auto can allow the browser to skip layout and painting work for content outside the viewport:

.article-section {
  content-visibility: auto;
  contain-intrinsic-size: 800px;
}

This is a rendering-work optimization. The documented guidance does not make it equivalent to loading="lazy" for deferring an image fetch. Use the HTML attribute when your goal is to defer an image request; use content-visibility only for the separate rendering optimization and test the result in your target browsers.

CSS background images need a different decision

The evidence for this technique documents ordinary <img> elements. It does not establish a native, universally equivalent fetch-deferral mechanism for background-image. Do not claim that content-visibility automatically lazy-loads a background image. If a visual is content that needs alternative text, an <img> is also the clearer semantic choice.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting

The image still downloads immediately

  • Check that the attribute is on the actual <img> element and reads exactly loading="lazy".
  • Confirm the image is actually below the initial viewport. The browser is allowed to fetch a lazy image before it becomes visible.
  • Inspect the request in browser developer tools; a preload or another page mechanism may have started the request independently.

The page jumps when an image appears

  • Add accurate width and height attributes.
  • Keep the CSS sizing rule height: auto so the displayed image follows that ratio as it scales.
  • Check that wrappers, cards and captions do not remove the reserved space.

The first-screen image feels slow

  • Remove loading="lazy" from an image that is visible or likely to be the LCP image.
  • Remember that loading="eager" and fetchpriority address different controls; eager loading alone does not raise priority.

A lazy image never appears

  • Give it nonzero, accurate dimensions so the browser can establish a layout box.
  • Check that an ancestor is not permanently preventing the element from intersecting the visible page.
  • Verify the image URL and response separately; lazy loading does not repair a missing or failed resource.

A background image is not deferred as expected

Do not infer behavior from an <img> test. The documented guidance here does not establish an equivalent native control for CSS backgrounds. Test the specific browser behavior you need, or use a semantic image with loading="lazy" when appropriate.

Performance and reliability checklist

  • Use loading="lazy" for genuinely below-the-fold content.
  • Keep the likely LCP and other initial-viewport images eager.
  • Declare accurate dimensions on every image to reserve space.
  • Use CSS for responsive sizing rather than trying to make CSS perform the network deferral.
  • Do not promise a fixed preload distance; the browser owns that threshold.
  • Treat content-visibility as a rendering optimization, not an image-fetch substitute.
  • Test on the viewport sizes and network conditions that matter to your users, especially pages with large galleries.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup:

If your immediate task is to capture a page image for documentation, visual review or an automated workflow rather than change how that page serves its images, ScreenshotNeo provides a website screenshot API and MCP server. It accepts a URL and returns PNG, JPEG, WebP or PDF output; it is complementary to implementing loading="lazy", not a replacement for that HTML behavior.

One request is enough (see the ScreenshotNeo API documentation):

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Before capture, ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and every response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf tools to Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create your free ScreenshotNeo account to get the 1,000 monthly screenshots without a card.

Frequently Asked Questions

Does loading="lazy" set a fixed number of pixels before an image loads?

No. The browser calculates the fetch distance, so the threshold can vary by user agent and conditions. Treat it as a hint, not a pixel-precise scheduling API.

Can content-visibility: auto replace the HTML loading attribute?

No. It is documented as a way to skip some offscreen layout and painting work. Use loading="lazy" when the requirement is deferring an image fetch.

Is ScreenshotNeo a replacement for lazy-loading images on my site?

No. ScreenshotNeo captures a rendered URL through an API or MCP server. Use the HTML and CSS technique in this article to control how your own page loads images.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.