Tutorials
Last updated on:
January 14, 2026

How to lazy load external videos in Framer for faster page speed

BRIX Templates Logo
Author
BRIX Templates
How to lazy load external videos in Framer for faster page speed
Article changelog

Jan 14, 2026 - Initial version of the article published

Table of contents

Every YouTube or Vimeo embed you add to your Framer site pulls in over 500KB of player resources—even when visitors never hit play. Drop three videos onto a page and you've silently added 1.5MB+ of bloat that drags down your entire site.

This guide walks you through two methods to eliminate that problem: a quick 2-minute patch using native browser lazy loading, and a proper solution using our brixLazyLoadVideo Code Override that delivers the best possible performance. The brixLazyLoadVideo override is free forever and takes 10 minutes or less to set up.

How Lazy Loading Reduces The Initial Load In Framer

Why external video embeds slow down Framer sites

When you drop a YouTube or Vimeo embed into your Framer page, it doesn't just fetch the video file. It loads the complete player infrastructure: JavaScript bundles, CSS files, fonts, tracking scripts, and preview thumbnails. A single YouTube embed brings in roughly 500-800KB of data that your visitor's browser has to download before the page feels responsive.

This happens the moment the page loads—even when the video sits below the fold, even when the visitor never scrolls to it, even when they have no intention of watching. When you stack multiple videos on a single page, the damage multiplies fast. Three embeds can pile on 1.5MB+ of unnecessary overhead. Ten videos on a portfolio page? You're looking at potentially 5MB of dead weight before your actual content even renders.

Lazy loading fixes this by postponing video resources until they're genuinely needed. Rather than loading heavy embeds immediately, lazy loading holds off until the video enters the viewport or until the user clicks play. The payoff is dramatically faster initial page loads, smoother user experience, and better performance across your entire Framer site.

Understanding the two approaches to lazy loading videos in Framer

There are two methods to lazy load videos in Framer, and each comes with different trade-offs.

Native lazy loading leverages the browser's built-in loading="lazy" attribute on iframes. You apply a small Code Override that patches this attribute onto your embeds, and the browser automatically postpones loading until the video approaches the viewport. It's dead simple—just two minutes to implement.

But it has real limitations. The browser still fetches the full 500KB+ player once triggered; you're just pushing back when that happens. You also surrender control over the exact timing—browsers decide based on scroll position and network conditions.

Click-to-load (using brixLazyLoadVideo) works completely differently. Instead of an iframe, visitors see a lightweight thumbnail image with a play button overlay. The actual video player only loads when someone clicks play.

This means zero video resources load unless a visitor explicitly chooses to watch. For a page with five videos, native lazy loading might defer 2MB initially but still loads everything as users scroll. Click-to-load keeps that 2MB off the page permanently unless users actually engage with the videos.

When to use each method: Go with native lazy loading if you have just 1-3 videos below the fold and want the quickest possible fix. Use click-to-load for landing pages, portfolios with multiple videos, pages where performance matters, or any video visible above the fold (where native lazy loading does nothing).

Method 1: Native lazy loading for iframes in Framer

This quick method adds browser-native lazy loading to your video embeds through a Code Override. It's the fastest fix but delivers moderate performance gains compared to the click-to-load approach.

Why you need a Code Override for lazy loading in Framer

When you use Framer's built-in YouTube, Vimeo, or Embed components, you don't have direct access to the iframe markup. The embed gets generated automatically, and there's no setting to enable lazy loading.

The workaround is straightforward: create a Code Override that patches the loading="lazy" attribute onto any iframe inside the target layer after it renders.

Adding the brixLazyIframe override to your Framer project

Follow these steps to add native lazy loading to your Framer embeds:

  1. In your Framer project, go to AssetsCodeNew Override
  2. Framer creates a new code file with example overrides
  3. Replace the contents with the code below
How To Create A New Code Override In The Framer Assets Panel
Where To Place The Lazy Loading Script In The Framer Tsx File

Paste this Code Override into the file:

import { forwardRef, useEffect, useRef, type ComponentType } from "react"

/*!
 * BRIX Templates Lazy Iframe for Framer
 * ----------------------------------------------------------------------------
 * Patches any <iframe> inside the target layer to add loading="lazy".
 * Uses browser-native lazy loading to defer iframe resources.
 *
 * Usage: Apply this override to any Frame/Stack containing an embed.
 *
 * Version: 1.0.0
 * Author: BRIX Templates
 */

export function brixLazyIframe(Component): ComponentType {
  return forwardRef((props: any, ref: any) => {
    const hostRef = useRef<HTMLElement | null>(null)

    //--------------------------------------------------------------------------
    // Ref Handling
    //--------------------------------------------------------------------------

    /**
     * Merges Framer's forwarded ref with our local ref
     * This ensures effects and links keep working properly
     */
    const setRef = (node: HTMLElement | null) => {
      hostRef.current = node

      if (typeof ref === "function") ref(node)
      else if (ref && "current" in ref) ref.current = node
    }

    //--------------------------------------------------------------------------
    // Iframe Patching
    //--------------------------------------------------------------------------

    useEffect(() => {
      const host = hostRef.current
      if (!host) return

      /**
       * Finds all iframes and adds lazy loading attribute
       */
      const patchIframes = () => {
        const iframes = host.querySelectorAll("iframe")
        iframes.forEach((iframe) => {
          // Browser-native lazy loading
          iframe.setAttribute("loading", "lazy")

          // Optional: hint to browser this is low priority
          iframe.setAttribute("fetchpriority", "low")
        })

        if (iframes.length > 0) {
          console.log("🎬 BRIX Lazy Iframe: Patched " + iframes.length + " iframe(s)")
        }
      }

      // Patch immediately
      patchIframes()

      // Some embeds inject the iframe after mount, so observe for changes
      const observer = new MutationObserver(patchIframes)
      observer.observe(host, { childList: true, subtree: true })

      return () => observer.disconnect()
    }, [])

    return <Component ref={setRef} {...props} />
  })
}
  1. Save the file
  2. Select the Frame or Stack that wraps your video embed
  3. In the right panel, find Code Overrides and select brixLazyIframe
  4. Preview or Publish your site to see it working (overrides don't run on the canvas)

The loading="lazy" attribute tells the browser to postpone loading until the iframe approaches the viewport.

How To Apply The Brixlazyiframe Override To The Video Frame In Framer

Limitations of native lazy loading for Framer videos

While native lazy loading is fast to implement, you should understand its drawbacks:

  • Browser controls the timing: You can't dictate exactly when the video starts loading—browsers decide based on scroll position and connection speed
  • Still loads heavy resources: Once triggered, the full YouTube/Vimeo player still downloads (500KB+), just delayed
  • No benefit for above-the-fold videos: Videos visible on initial page load won't be lazy loaded whatsoever
  • Inconsistent browser behavior: Different browsers handle the loading threshold differently

For pages with multiple videos or where performance is critical, the click-to-load method below delivers substantially better results.

Method 2: Click-to-load videos in Framer with brixLazyLoadVideo

This method delivers maximum performance gains by loading absolutely nothing until the user clicks play. Visitors see a fast-loading thumbnail image with a play button overlay, and the actual video player only loads on interaction.

Why click-to-load is the better solution for Framer video performance

The click-to-load approach offers significant advantages over native lazy loading:

  • Zero initial resource cost: No video player JavaScript, CSS, or connection overhead until user interaction
  • Immediate page speed improvement: Save 500KB+ per video on initial page load
  • Better user experience: Visitors see a crisp thumbnail instantly instead of waiting for an iframe to load
  • Works for above-the-fold videos: Even hero videos benefit because resources only load on click
  • Consistent behavior: No browser variations—you control exactly when videos load

How the brixLazyLoadVideo override works in Framer

Since Code Overrides in Framer can't have Property Controls (those are reserved for Code Components), you need a way for designers to configure each video without touching code.

The cleanest solution: store the video URL in the layer's Link field. The override reads the link, extracts the video ID, and handles everything else automatically.

This approach scales beautifully for:

  • Landing pages with hero videos
  • Portfolio grids
  • CMS-powered video galleries (bind the Link to a CMS field)

Adding the brixLazyLoadVideo override to your Framer project

First, add the click-to-load override to your project. This is a one-time setup that you can reuse across your entire site.

Go to AssetsCodeNew Override (or open your existing overrides file) and add this code:

import { forwardRef, useEffect, useMemo, useState, type ComponentType } from "react"

/*!
 * BRIX Templates Lazy Load Video for Framer
 * ----------------------------------------------------------------------------
 * Loads YouTube/Vimeo videos only when users click play.
 * Uses lightweight thumbnails until interaction for maximum performance.
 *
 * Usage: 
 * 1. Design your thumbnail (Image + play button) in a Frame
 * 2. Set the Frame's Link to your YouTube/Vimeo URL
 * 3. Apply this override to the Frame
 *
 * Supported URL formats:
 * - https://www.youtube.com/watch?v=VIDEO_ID
 * - https://youtu.be/VIDEO_ID
 * - https://vimeo.com/VIDEO_ID
 * - youtube:VIDEO_ID (compact format)
 * - vimeo:VIDEO_ID (compact format)
 *
 * Version: 1.0.1
 * Author: BRIX Templates
 */

//--------------------------------------------------------------------------
// Types
//--------------------------------------------------------------------------

type Provider = "youtube" | "vimeo"
type ParsedVideo = { provider: Provider; id: string } | null

//--------------------------------------------------------------------------
// Utility Functions
//--------------------------------------------------------------------------

/**
 * Detects if user is on a mobile device
 * Used to determine if videos should be muted for autoplay compatibility
 */
function isMobileDevice(): boolean {
  if (typeof window === "undefined") return false
  const maxWidth = 767
  return (
    window.innerWidth <= maxWidth ||
    /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
  )
}

//--------------------------------------------------------------------------
// URL Parsing
//--------------------------------------------------------------------------

/**
 * Extracts provider and video ID from various URL formats
 */
function parseVideoUrl(raw: string): ParsedVideo {
  if (!raw) return null

  // Support compact "provider:id" format (youtube:dQw4w9WgXcQ)
  const compact = raw.match(/^(youtube|vimeo)\s*:\s*([a-zA-Z0-9_-]+)$/i)
  if (compact) {
    return { provider: compact[1].toLowerCase() as Provider, id: compact[2] }
  }

  let url: URL
  try {
    url = new URL(raw)
  } catch {
    return null
  }

  const host = url.hostname.replace(/^www\./, "")
  const pathParts = url.pathname.split("/").filter(Boolean)

  // --- YouTube ---
  if (host === "youtu.be") {
    const id = pathParts[0]
    return id ? { provider: "youtube", id } : null
  }

  if (host.endsWith("youtube.com") || host === "youtube-nocookie.com") {
    // https://youtube.com/watch?v=ID
    if (url.pathname === "/watch") {
      const id = url.searchParams.get("v")
      return id ? { provider: "youtube", id } : null
    }

    // https://youtube.com/embed/ID
    if (pathParts[0] === "embed" && pathParts[1]) {
      return { provider: "youtube", id: pathParts[1] }
    }
  }

  // --- Vimeo ---
  if (host.endsWith("vimeo.com")) {
    // https://vimeo.com/507360544
    const maybeId = pathParts[0]
    if (maybeId && /^\d+$/.test(maybeId)) {
      return { provider: "vimeo", id: maybeId }
    }

    // https://player.vimeo.com/video/507360544
    if (pathParts[0] === "video" && pathParts[1] && /^\d+$/.test(pathParts[1])) {
      return { provider: "vimeo", id: pathParts[1] }
    }
  }

  if (host === "player.vimeo.com" && pathParts[0] === "video" && pathParts[1]) {
    return /^\d+$/.test(pathParts[1]) ? { provider: "vimeo", id: pathParts[1] } : null
  }

  return null
}

//--------------------------------------------------------------------------
// Embed URL Builder
//--------------------------------------------------------------------------

/**
 * Builds the iframe src URL with autoplay parameters
 * Automatically mutes on mobile for autoplay compatibility
 */
function buildEmbedSrc(video: { provider: Provider; id: string }): string {
  const shouldMute = isMobileDevice()

  if (video.provider === "youtube") {
    const params = new URLSearchParams({
      autoplay: "1",
      playsinline: "1",
      rel: "0",
      modestbranding: "1",
    })
    if (shouldMute) params.set("mute", "1")
    return `https://www.youtube.com/embed/${video.id}?${params.toString()}`
  }

  // Vimeo
  const params = new URLSearchParams({
    autoplay: "1",
    title: "0",
    byline: "0",
    portrait: "0",
  })
  if (shouldMute) params.set("muted", "1")
  return `https://player.vimeo.com/video/${video.id}?${params.toString()}`
}

//--------------------------------------------------------------------------
// Override
//--------------------------------------------------------------------------

export function brixLazyLoadVideo(Component): ComponentType {
  return forwardRef((props: any, ref: any) => {
    // Framer layers with links expose href
    // Check common fallbacks to be safe
    const href: string =
      props?.href ?? props?.link ?? props?.url ?? props?.videoUrl ?? ""

    const video = useMemo(() => parseVideoUrl(href), [href])
    const [isLoaded, setIsLoaded] = useState(false)

    // Log when video is ready
    useEffect(() => {
      if (video) {
        console.log("🎬 BRIX Lazy Load Video: Ready - " + video.provider + " (" + video.id + ")")
      }
    }, [video])

    /**
     * Handles click/tap events
     * Prevents navigation and loads the video player
     */
    const onTap = (event?: any) => {
      // If this is an <a>, stop navigation
      event?.preventDefault?.()

      if (!video) {
        // No valid video URL found, let normal behavior happen
        props?.onTap?.(event)
        props?.onClick?.(event)
        return
      }

      // Load video on first click
      if (!isLoaded) {
        setIsLoaded(true)
        console.log("🎬 BRIX Lazy Load Video: Playing - " + video.provider + " (" + video.id + ")")
      }

      // Preserve any existing handlers
      props?.onTap?.(event)
      props?.onClick?.(event)
    }

    // If URL isn't parseable, attach handler but do nothing special
    if (!video) {
      return <Component ref={ref} {...props} onTap={onTap} />
    }

    const iframeSrc = buildEmbedSrc(video)

    return (
      <Component
        ref={ref}
        {...props}
        onTap={onTap}
        style={{
          ...props?.style,
          cursor: isLoaded ? props?.style?.cursor : "pointer",
        }}
      >
        {props.children}

        {isLoaded && (
          <iframe
            key={`${video.provider}:${video.id}`}
            src={iframeSrc}
            title="Video player"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowFullScreen
            loading="eager"
            style={{
              position: "absolute",
              inset: 0,
              width: "100%",
              height: "100%",
              border: 0,
            }}
          />
        )}
      </Component>
    )
  })
}

Save the file. The override is now available across your project.

Adding lazy-loaded videos to your Framer page

With the override saved, adding lazy-loaded videos is straightforward. Each video just needs a thumbnail and a link.

  1. Add a Frame to your page where you want the video
  2. Set the Frame's size to your desired video dimensions (e.g., 16:9 aspect ratio)
  3. Add an Image inside the Frame for your video thumbnail
  4. Set the Image to Fill the Frame
  5. Add a play button icon on top (optional but recommended)
  6. Select the parent Frame and set its Link to your YouTube or Vimeo URL
  7. With the Frame selected, go to Code Overrides in the right panel and choose brixLazyLoadVideo
  8. Preview your site—the video should only load when you click
How To Configure The Video Link For Click To Load In Framer

Supported URL formats for Framer lazy-loaded videos

The override accepts multiple URL formats:

YouTube:

Vimeo:

The compact format is handy when you want to keep links short, especially in CMS setups.

How to find your YouTube video ID for Framer lazy loading

The YouTube video ID is the code after v= in any YouTube URL.

For this URL: https://www.youtube.com/watch?v=dQw4w9WgXcQ

The video ID is: dQw4w9WgXcQ

How to find your Vimeo video ID for Framer lazy loading

The Vimeo video ID is the number after vimeo.com/ in any Vimeo URL.

For this URL: https://vimeo.com/507360544

The video ID is: 507360544

How to get video thumbnails for Framer lazy-loaded videos

You need a thumbnail image for each video. Here are the easiest ways to get them:

For YouTube videos, use this URL pattern to grab the default thumbnail:

https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg

Replace VIDEO_ID with your actual video ID. Download this image and upload it to your Framer project.

For Vimeo videos, the thumbnail API is limited, so the easiest option is to take a screenshot from the video or upload your own custom thumbnail.

You can also use any custom thumbnail you prefer for either platform—it doesn't have to be the default video thumbnail. Just upload your image and use it inside your video wrapper Frame.

Using brixLazyLoadVideo with Framer CMS

The click-to-load pattern integrates seamlessly with Framer CMS for dynamic video galleries or portfolio pages.

First, create these fields in your CMS Collection:

  • Video URL (Link): Stores the YouTube or Vimeo URL
  • Video Thumbnail (Image): Stores the thumbnail image

Then, on your Collection page or Collection list:

  1. Add a Frame with the proper aspect ratio styling
  2. Add an Image inside and connect it to the Video Thumbnail field
  3. Select the parent Frame and connect its Link to the Video URL field
  4. Apply the brixLazyLoadVideo override to the Frame

Now every CMS item automatically gets lazy-loaded video functionality without any additional code.

Testing your Framer video lazy loading implementation

After publishing your site, verify that lazy loading works correctly with these checks.

Checking network requests in your Framer video pages

  1. Preview or Publish your Framer site (overrides only run in Preview/Published mode, not on the canvas)
  2. Open Chrome and navigate to your page
  3. Press F12 to open Developer Tools
  4. Go to the Network tab
  5. Refresh the page
  6. Look for YouTube or Vimeo requests—there should be none until you click a video thumbnail
  7. Click a video thumbnail and watch the Network tab populate with video resources

Troubleshooting common Framer video lazy loading issues

  • Video navigates away instead of playing: Your wrapper Frame is acting like a normal link. Make sure the brixLazyLoadVideo override is applied to the same Frame that has the Link set. The override intercepts the click and prevents navigation.
  • Iframe appears but doesn't fill the container: Your wrapper Frame likely has no fixed height (common when sizing is set to "Hug"). Give the Frame a specific height or use an aspect ratio lock. If you want rounded corners, enable Clip on the Frame so the iframe gets masked.
  • Override doesn't seem to run: Code Overrides only execute in Preview or Published mode. They don't run on the Framer canvas. Make sure you're testing in Preview.
  • CMS-connected videos don't work: Don't try to access CMS internals through code. Use Framer's built-in field binding to connect the Link and Image properties to your CMS fields.
  • Play button doesn't show: The override doesn't inject a play button—you design that yourself in Framer. Add an icon or shape on top of your thumbnail image.

Frequently asked questions about lazy loading videos in Framer

What is lazy loading for videos in Framer?

Lazy loading is a performance technique that postpones loading video resources until they're genuinely needed. Instead of loading heavy YouTube or Vimeo embeds the moment your page loads, lazy loading waits until the video enters the viewport or until the user clicks play.

This dramatically cuts initial page load time because video embeds typically add 500KB+ of scripts and resources. In Framer, you can implement lazy loading using a Code Override that patches the native loading="lazy" attribute onto iframes, or more effectively using a click-to-load pattern that displays a thumbnail until user interaction. The click-to-load approach delivers the best performance because it loads zero video resources until someone actually wants to watch.

Why are YouTube and Vimeo embeds slowing down my Framer site?

Every YouTube or Vimeo embed fetches the entire video player infrastructure immediately—JavaScript bundles, CSS files, fonts, tracking scripts, and preview thumbnails. A single YouTube embed adds roughly 500-800KB of data that your visitor's browser must download before the page feels responsive.

This happens even when the video sits below the fold or when the visitor never plans to watch it. When you have multiple videos on a page, this stacks up quickly: three embeds can add 1.5MB+ of unnecessary initial load. The solution is implementing lazy loading so these resources only load when needed, as covered in Method 2 of this guide.

What's the difference between native lazy loading and click-to-load for Framer videos?

Native lazy loading using loading="lazy" tells the browser to postpone loading an iframe until it approaches the viewport. It's simple to implement but the browser still fetches the full video player once triggered—you're just pushing back when that happens.

Click-to-load (facade pattern) displays a static thumbnail image with a play button. The actual video player never loads unless someone clicks. This means zero video resources on initial page load, regardless of scroll position. For a page with five videos, native lazy loading might defer 2MB initially but still loads everything as users scroll. Click-to-load keeps that 2MB off the page permanently unless users actually engage with videos—making it the superior choice for most situations.

How do Code Overrides work for video lazy loading in Framer?

Code Overrides in Framer are small React Higher-Order Components you attach to any layer. They let you modify props, events, styles, and behavior at render time. For video lazy loading, overrides can patch iframe attributes or intercept click events to inject video players on demand.

One important detail: overrides only run in Preview and Published mode—they don't execute on the Framer canvas. This is actually perfect for lazy loading because you want to test real performance behavior anyway. The brixLazyLoadVideo override reads the video URL from the layer's Link field, making it designer-friendly since no code changes are needed per video.

Does lazy loading videos affect SEO for Framer sites?

Lazy loading videos actually helps SEO rather than hurting it. Search engines favor fast-loading pages, and cutting initial page weight by lazy loading videos directly improves load speed metrics.

Google's crawlers are sophisticated enough to understand lazy-loaded content. The key is ensuring your page still has relevant text content and that video thumbnails include descriptive alt text for accessibility and indexing. For click-to-load implementations, the thumbnail images provide visual context that search engines can index. Faster pages translate to better user experience metrics, lower bounce rates, and ultimately better search rankings.

Can I lazy load videos in Framer CMS collections?

Yes, both lazy loading methods work with Framer CMS. For native lazy loading, apply the brixLazyIframe override to any Frame containing a CMS-bound embed.

For click-to-load, create CMS fields for Video URL and Video Thumbnail, then bind these to the Frame's Link property and the Image source. The brixLazyLoadVideo override automatically initializes all videos on the page, including those generated dynamically from CMS collections. This makes it perfect for video portfolios, course platforms, or any site with multiple dynamic videos.

Will lazy-loaded videos autoplay when clicked in Framer?

Yes, both the YouTube and Vimeo embeds are configured with autoplay parameters. When a user clicks the thumbnail, the video player loads and begins playing immediately.

On mobile devices, browsers have strict autoplay policies that may require videos to be muted for automatic playback. The iframe parameters include playsinline for mobile compatibility. If autoplay doesn't work on a specific device, users can simply tap the player controls to start playback. This is a browser-level restriction, not a limitation of the lazy loading implementation.

How many videos can I lazy load on a single Framer page?

There's no practical limit to how many videos you can lazy load on a page. In fact, more videos makes lazy loading more valuable.

Without lazy loading, a page with 10 video embeds would need to fetch 5MB+ of resources upfront. With click-to-load lazy loading, that same page loads with zero video overhead until users interact. Each video loads independently when clicked, so even with 50 videos on a page, only the ones users actually watch consume resources. This makes click-to-load ideal for video galleries, course libraries, or any page with many videos.

What video hosting platforms work with lazy loading in Framer?

The brixLazyIframe override works with any iframe-based embed since it simply patches the loading attribute. This includes YouTube, Vimeo, Wistia, Loom, and others.

The brixLazyLoadVideo override specifically supports YouTube and Vimeo, which cover the vast majority of use cases. The URL parser handles multiple formats for both platforms. For other providers, you could extend the override by adding new parsing logic, or use the native lazy loading approach with any iframe embed.

Should I lazy load above-the-fold videos in Framer?

Yes, but only with the click-to-load method. Native loading="lazy" has no effect on above-the-fold content because the browser loads anything visible in the initial viewport immediately.

However, click-to-load works regardless of position because it replaces the video with a thumbnail until user interaction. For hero videos or any prominent video visible on page load, click-to-load is the only way to avoid the performance hit. The thumbnail loads instantly, the page renders fast, and the actual video player only loads when the user demonstrates intent by clicking play.

Conclusion

Lazy loading external videos is one of the highest-impact performance optimizations for Framer sites. The click-to-load approach using brixLazyLoadVideo delivers maximum performance gains by loading zero video resources until users actually want to watch. For simpler implementations, native loading="lazy" via brixLazyIframe provides a quick fix with moderate benefits.

Start with the click-to-load method for any page where performance matters—especially landing pages, portfolios with multiple videos, or CMS-driven video galleries. The one-time override setup pays dividends across your entire site.

For advanced implementations like custom video players, analytics integration, or complex CMS setups, our Framer development team can create tailored solutions that align with your specific requirements.

BRIX Templates Logo
About BRIX Templates

At BRIX Templates we craft beautiful, modern and easy to use Webflow templates & UI Kits.

Explore our Webflow templates
Join the conversation
Join our monthly Webflow email newsletter!

Receive one monthly email newsletter with the best articles, resources, tutorials, and free cloneables from BRIX Templates!

Webflow Newsletter
Thanks for joining our Webflow email newsletter
Oops! Something went wrong while submitting the form.
How to lazy load external videos in Webflow for faster page speed

How to lazy load external videos in Webflow for faster page speed

Learn two ways to lazy load YouTube and Vimeo in Webflow: quick native fix plus click-to-load pattern for better performance.

Jan 13, 2026
How to block personal emails in Framer forms and capture only business leads

How to block personal emails in Framer forms and capture only business leads

Step-by-step guide to implementing work-email-only validation in Framer forms. Block personal providers and improve lead quality instantly.

Jan 12, 2026
How to track Framer button clicks with Google Tag Manager

How to track Framer button clicks with Google Tag Manager

Track Framer button clicks with Google Tag Manager and send detailed GA4 events—no code required. Complete step-by-step guide.

Jan 9, 2026