Technical SEO 10 min read

Lazy Loading Guide: Improve Page Speed Without Breaking SEO

Learn how to implement lazy loading correctly for images, videos, and content. Improve page speed while avoiding common SEO pitfalls.

By Rankture Team
Lazy Loading Guide: Improve Page Speed Without Breaking SEO

Lazy loading defers the loading of resources until they’re needed, dramatically improving initial page load times. But implement it wrong, and you can hurt your SEO and user experience.

Here’s how to do lazy loading right.

What Is Lazy Loading?

Lazy loading is a technique that delays loading non-critical resources until they’re needed. Instead of loading everything at once, resources load as the user scrolls or interacts.

Commonly lazy loaded:

Benefits of Lazy Loading

Performance Benefits

SEO Benefits

Native Lazy Loading

Modern browsers support native lazy loading—no JavaScript required.

For Images

<!-- Below-fold images: lazy load -->
<img src="photo.jpg" loading="lazy" alt="Description" width="800" height="600">

<!-- Above-fold images: eager load (default) -->
<img src="hero.jpg" loading="eager" alt="Hero" width="1200" height="600">

For Iframes

<!-- Lazy load embedded content -->
<iframe src="https://youtube.com/embed/xyz" loading="lazy"></iframe>

Browser Support

Native lazy loading is supported by:

For older browsers, content loads normally (graceful degradation).

What NOT to Lazy Load

The LCP Element

Never lazy load your LCP element. This is typically:

Lazy loading the LCP element delays the largest content, directly hurting your LCP score.

<!-- WRONG: Lazy loading the hero -->
<img src="hero.jpg" loading="lazy" alt="Hero">

<!-- CORRECT: Eager load the hero -->
<img src="hero.jpg" loading="eager" alt="Hero">
<!-- Or simply omit loading attribute (defaults to eager) -->
<img src="hero.jpg" alt="Hero">

Content Google Needs to See

If lazy loading prevents content from being in the initial HTML, Google may not see it:

JavaScript Lazy Loading

For more control, use JavaScript with Intersection Observer.

Basic Implementation

// Create observer
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' // Load 200px before entering viewport
});

// Observe all lazy images
document.querySelectorAll('img[data-src]').forEach(img => {
  observer.observe(img);
});

HTML for JavaScript Lazy Loading

<!-- Use data-src instead of src -->
<img data-src="photo.jpg" alt="Description" width="800" height="600">

When to Use JavaScript vs Native

Use native lazy loading when:

Use JavaScript lazy loading when:

Preventing CLS with Lazy Loading

Lazy loaded images can cause layout shift if space isn’t reserved.

Always Include Dimensions

<!-- Good: Dimensions prevent CLS -->
<img 
  src="photo.jpg" 
  loading="lazy" 
  width="800" 
  height="600" 
  alt="Description"
>

Use Aspect Ratio

<img 
  src="photo.jpg" 
  loading="lazy" 
  alt="Description"
  style="aspect-ratio: 4/3; width: 100%;"
>

Use Placeholder Techniques

Low Quality Image Placeholder (LQIP):

<img 
  src="photo-tiny.jpg" 
  data-src="photo-full.jpg" 
  alt="Description"
  class="lazyload blur-up"
>

CSS Blur-up effect:

.lazyload {
  filter: blur(10px);
  transition: filter 0.3s;
}

.lazyload.loaded {
  filter: blur(0);
}

Solid color placeholder:

<div style="background: #f0f0f0; aspect-ratio: 4/3;">
  <img 
    src="photo.jpg" 
    loading="lazy" 
    alt="Description"
    onload="this.parentElement.style.background='none'"
  >
</div>

Lazy Loading Videos

YouTube Embeds

Don’t embed YouTube directly—it loads megabytes of scripts.

Better: Load facade, embed on click:

<div class="youtube-facade" data-video-id="abc123">
  <img src="youtube-thumbnail.jpg" alt="Video title">
  <button class="play-button">Play</button>
</div>

<script>
document.querySelectorAll('.youtube-facade').forEach(el => {
  el.addEventListener('click', () => {
    const iframe = document.createElement('iframe');
    iframe.src = `https://youtube.com/embed/${el.dataset.videoId}?autoplay=1`;
    iframe.allow = 'autoplay';
    el.replaceWith(iframe);
  });
});
</script>

Native Video

<video 
  poster="video-poster.jpg" 
  preload="none"
  controls
>
  <source src="video.mp4" type="video/mp4">
</video>

preload="none" prevents video from loading until played.

Lazy Loading Third-Party Scripts

Heavy scripts can delay interactivity.

Delay Until Interaction

let loaded = false;

function loadChatWidget() {
  if (loaded) return;
  loaded = true;
  
  const script = document.createElement('script');
  script.src = 'https://chat-widget.com/embed.js';
  document.body.appendChild(script);
}

// Load on scroll or after delay
window.addEventListener('scroll', loadChatWidget, { once: true });
setTimeout(loadChatWidget, 5000);

Common Scripts to Defer

SEO Considerations

What Google Sees

Google renders JavaScript, but:

Best Practices for SEO

  1. Critical content in initial HTML: Don’t lazy load main content
  2. Use native lazy loading: Google understands loading="lazy"
  3. Provide fallbacks: Content should work without JavaScript
  4. Test in Search Console: URL Inspection shows rendered page

Testing What Google Sees

  1. Google Search Console > URL Inspection > View tested page
  2. Compare crawled HTML vs rendered HTML
  3. Check if lazy-loaded content appears

Lazy Loading Checklist

Implementation

Preventing CLS

SEO Safety

User Experience


Related Resources:

Tags:

lazy loading page speed core web vitals performance images

Share this article:

Ready to improve your SEO?

Get a free SEO audit and see exactly what needs fixing on your site

Start Free Audit