⚡IntermediatePerformance and Loading

Lazy Loading

Defer offscreen images and iframes with loading="lazy" to speed up initial page load.

Overview

Lazy loading defers the download of offscreen images and iframes until they are near the viewport, reducing the amount of data loaded on initial page render. The loading attribute on <img> and <iframe> provides native browser lazy loading no JavaScript required: - loading="lazy": defers loading until the element is near the viewport - loading="eager": loads immediately (default behavior) - loading="auto": browser decides (deprecated/inconsistent) This is one of the simplest, highest-impact performance optimizations. Adding loading="lazy" to below-the-fold images can dramatically reduce initial page weight.

Key Points

  • •loading="lazy" defers images/iframes until they approach the viewport
  • •loading="eager" (default) loads immediately regardless of position
  • •Never use loading="lazy" on above-the-fold images it delays LCP
  • •Always specify width and height on lazy images to prevent layout shift
  • •The browser determines the threshold distance typically 1-2 viewport heights away
  • •Use loading="lazy" on iframes too: maps, YouTube embeds, widgets below the fold

Examples

Lazy loading images

<!-- Hero image: never lazy load it's above the fold -->
<img
  src="hero.webp"
  alt="Hero banner"
  width="1200"
  height="600"
  loading="eager"
>

<!-- Article thumbnail: below the fold lazy load -->
<img
  src="article-thumb.jpg"
  alt="Article preview"
  width="400"
  height="225"
  loading="lazy"
>

<!-- Many images in a long list: all lazy except the first few -->
<ul class="product-grid">
  <li><img src="p1.jpg" alt="Product 1" width="300" height="300" loading="eager"></li>
  <li><img src="p2.jpg" alt="Product 2" width="300" height="300" loading="eager"></li>
  <li><img src="p3.jpg" alt="Product 3" width="300" height="300" loading="lazy"></li>
  <!-- All subsequent items use loading="lazy" -->
</ul>

Lazy loading iframes

<!-- Map below the fold lazy load -->
<iframe
  src="https://www.google.com/maps/embed?pb=..."
  width="600"
  height="450"
  title="Our office location"
  loading="lazy"
  style="border:0"
></iframe>

<!-- YouTube video embed lazy load -->
<iframe
  src="https://www.youtube.com/embed/VIDEO_ID"
  title="Product demo video"
  width="560"
  height="315"
  loading="lazy"
  frameborder="0"
  allowfullscreen
></iframe>

Intersection Observer API (for custom lazy loading)

<!-- Fallback for older browsers or custom triggers -->
<img
  data-src="large-image.jpg"
  alt="Description"
  src="placeholder.jpg"
  class="lazy"
  width="800"
  height="400"
>

<script>
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img);
    }
  });
}, { rootMargin: '200px' });

document.querySelectorAll('img.lazy').forEach(img => observer.observe(img));
</script>

Use this pattern only when native lazy loading doesn't fit your use case.

Common Mistakes

  • Adding loading="lazy" to the LCP (hero) image it delays the most important visual element
  • Not specifying width/height with lazy images causes cumulative layout shift when images load
  • Lazy loading images above the fold they should load immediately

Note

A simple rule: the first 2-3 images visible on load get loading="eager" (or no attribute). Everything else below gets loading="lazy". This pattern alone can cut initial page weight by 50%+ on image-heavy pages.

Exercises

Write HTML to solve each exercise. Use Preview to see it render in a live iframe, then mark as done.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What does loading="lazy" do on an <img>?