How to Lazy Load Videos in Shopify (2026)

Last updated
•
Expert reviewed
•
5 min read

Key takeaways

  • Native video elements should use preload="none" plus a poster, and load their source with an Intersection Observer. The loading attribute only works on images and iframes.
  • YouTube and Vimeo embeds use a “facade” pattern — show a clickable thumbnail, load the iframe only when clicked.
  • Background videos should load only when the section scrolls into view, not on page load.
  • Unoptimized video is one of the largest contributors to slow Shopify page load times.

To lazy load videos in Shopify, replace YouTube and Vimeo iframes with a clickable thumbnail (the facade pattern), give self-hosted <video> tags preload="none" and a poster, and load background videos only when their section scrolls into view.

Video is one of the heaviest assets on a page. An embed that loads on page load slows the page even for visitors who scroll past it without watching.

How to add lazy loading to native video in Shopify

For self-hosted video files uploaded to Shopify’s asset system or a CDN, use preload="none" and a poster image. The loading attribute only works on <img> and <iframe>; browsers ignore it on <video>. To defer the file itself, load its source with an Intersection Observer (see the background-video code below).

<video
    src="{{ section.settings.video_url }}"
    poster="{{ section.settings.poster_image | image_url: width: 1200 }}"
    preload="none"
    muted
    playsinline
    loop
>
    Your browser doesn't support video.
</video>

Key attributes:

preload="none" — prevents the browser from downloading any video data until the user interacts with the player. Without this, browsers often prefetch video metadata or even the first few seconds of video, wasting bandwidth.

poster — shows a still image while the video hasn’t loaded. Always include this. Without a poster, visitors see a blank gray rectangle until the video loads. The poster image should be pre-loaded (don’t lazy load it).

For images, see how to lazy load images in Shopify.


The facade pattern for YouTube and Vimeo embeds

YouTube and Vimeo iframes are among the biggest performance problems on Shopify stores. Each embed loads its player scripts from YouTube’s or Vimeo’s servers (around 1MB of scripts per YouTube embed), even if the visitor never watches the video.

The facade pattern: replace the iframe with a clickable thumbnail image. When the visitor clicks to play, replace the image with the actual iframe.

Here’s a basic implementation:

<div class="video-facade" data-video-id="YOUR_YOUTUBE_ID">
    <img
        src="https://img.youtube.com/vi/YOUR_YOUTUBE_ID/maxresdefault.jpg"
        alt="Video thumbnail"
        loading="lazy"
        style="width:100%; cursor:pointer;"
    />
    <button class="video-play-btn" aria-label="Play video">
        <!-- Play icon SVG here -->
    </button>
</div>
document.querySelectorAll('.video-facade').forEach(function (facade) {
    facade.addEventListener('click', function () {
        var videoId = facade.dataset.videoId
        var iframe = document.createElement('iframe')
        iframe.src = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1'
        iframe.allow = 'autoplay; encrypted-media'
        iframe.style.width = '100%'
        iframe.style.height = '100%'
        facade.replaceWith(iframe)
    })
})

For Vimeo: replace img.youtube.com/vi/ID/maxresdefault.jpg with a Vimeo thumbnail URL and update the embed URL to https://player.vimeo.com/video/ID?autoplay=1.

Easier option: Use the Lite YouTube Embed web component (a popular open-source library) which implements the facade pattern with a single HTML element.

For more speed fixes, see how to speed up a Shopify theme.


Lazy loading background videos

Background videos (the kind that auto-play as a decorative element behind text) are particularly wasteful if they load for every visitor who lands on the page.

Approach: load video only when the section scrolls into view.

var videoSection = document.querySelector('.hero-video-section')
var videoEl = videoSection.querySelector('video')

var observer = new IntersectionObserver(
    function (entries) {
        entries.forEach(function (entry) {
            if (entry.isIntersecting) {
                // Load the video
                var source = videoEl.querySelector('source')
                if (source && source.dataset.src) {
                    source.src = source.dataset.src
                    videoEl.load()
                    videoEl.play()
                }
                observer.disconnect()
            }
        })
    },
    {threshold: 0.1},
)

observer.observe(videoSection)

Use this with a <source data-src="..."> instead of <source src="..."> to prevent the browser from downloading the video source before the Intersection Observer fires.

For the hero section (above the fold): background video in the hero loads immediately regardless — it’s already visible. In this case, use preload="metadata" instead of preload="none" so the browser prepares to play the video quickly.

For product videos, see how to add video to a Shopify product gallery.

Build fast Shopify video sections by describing them to Fudge.
Start free trial

Should you use video in Shopify at all?

Video is worth it when:

  • It shows something that can’t be conveyed in a photo (fabric texture, product in motion, a process)
  • It’s well-produced (low-quality video hurts trust)
  • You’ve implemented lazy loading (otherwise the performance cost is too high)

Video is not worth it when:

  • It’s purely decorative with no product-related purpose
  • It auto-plays with sound (annoying, and most browsers block it anyway)
  • The same message could be delivered more efficiently with a well-shot photo

Consider GIF alternatives. For short looping clips (2-5 seconds), an MP4 video with autoplay muted loop is typically 60-80% smaller than an equivalent GIF while looking identical.


Checking video performance impact

Run your product or homepage URL through PageSpeed Insights. Video embeds will often trigger:

  • “Reduce unused JavaScript” — from YouTube’s API loading
  • “Avoid enormous network payloads” — if video is loading on page load
  • “Lazy load third-party resources with facades” - flags YouTube and Vimeo embeds

After implementing the facade pattern, re-run PageSpeed — you should see improvements in both score and Total Blocking Time.


FAQ

Will lazy-loading videos hurt my Shopify SEO?

No, with correct implementation. Google handles lazy-loaded content fine when standard techniques (native loading="lazy", Intersection Observer with reasonable thresholds) are used. The SEO win is the speed improvement — Core Web Vitals scores improve, which is a soft ranking signal. Avoid lazy-loading content above the fold.

What's the difference between the facade pattern and native lazy-loading?

Native loading="lazy" on a YouTube or Vimeo iframe defers it until it's near the viewport. The facade pattern replaces the iframe entirely with a thumbnail until clicked, so the iframe and its scripts only load on user intent. For YouTube/Vimeo embeds, the facade saves more weight (around 1MB of scripts per YouTube embed) than native lazy loading. The cleanest way to add it without writing the JavaScript yourself: describe what you want to Fudge, the AI operator for Shopify stores ("apply the facade pattern to YouTube embeds across the site"), and it writes the change into your theme as a draft you approve. Slow pages are also part of its SEO checks, so heavy embeds like these can show up before you go looking for them.

Should I lazy-load the hero video?

No. The hero is above the fold and lazy-loading content the user will see immediately just creates a delayed render. Use preload="metadata" for hero videos to prepare playback without downloading the full file. Lazy-loading is for video below the fold.

Can autoplay videos still lazy-load?

Yes — defer the iframe/video until the section enters the viewport via Intersection Observer, then trigger autoplay. Browsers require autoplay videos to be muted regardless of when they load. The pattern: don't load the video at all until visible, then auto-play muted once it's loaded.

How do I verify videos are actually lazy-loaded?

Open Chrome DevTools → Network tab → filter by "media". Reload the page and watch what loads on initial render vs. on scroll. Videos correctly lazy-loaded won't appear in the Network tab until you scroll near them. PageSpeed Insights also flags YouTube and Vimeo embeds without a facade under "Lazy load third-party resources with facades".

Jacques's signature
Build fast Shopify sections with proper video handling by describing them.

You might also be interested in

Jacques Blom
Jacques Blom
CTO at Fudge.