Lazy loading YouTube embeds | Eterno Devir<br>Lazy loading YouTube embeds<br>Since I'm adding many YouTube videos to the new Web Gems section, I decided to lazy load all YouTube embeds on the website.<br>The concept is straightforward: instead of loading the full YouTube player for every video on a page, only the video's thumbnail and a small bit of CSS to mimic the player interface are loaded.<br>The actual player is only requested and loaded if the reader clicks "Play".<br>This makes pages load significantly faster and saves bandwidth. You never know if the person reading lives on a sailboat where every bit of bandwidth matters.<br>To achieve this, I turned to paulirish/lite-youtube-embed.<br>It is a small JavaScript file that handles the thumbnail display and the iframe swap on play, paired with the necessary CSS for the player replica.<br>On top of its simplicity, lite-youtube-embed uses youtube-nocookie.com by default, so no extra privacy-friendly changes were necessary.<br>Beyond curl -O -L these two files, it was just a matter of writing a Hugo shortcode and figuring out a workaround to support playlists.<br>YouTube videos provide different thumbnail qualities, ranging from default to maxres.<br>I defined maxres as default value for poster-quality, as it looks better and makes the shortcode usage a bit more ergonomic.<br>However, a given video may not provide maxres, which requires finding the highest quality available.<br>For videos, the final shortcode syntax looks like this:<br>{{<br>lite-youtube<br>src="https://www.youtube.com/watch?v=SrKj4hYic5A"<br>poster-quality="sd"<br>>}}
For playlists, where the workaround was required, it looks like this:<br>{{<br>lite-youtube<br>src="https://www.youtube.com/playlist?list=PLdJRJcZwR07E0CsTwSAPK-4GdQyVLvyVN"<br>poster-id="eY-eyZuW_Uk"<br>>}}
Even though the lite-yt-embed.js and lite-yt-embed.css files are tiny (3.63 kB and 1.88 kB), it would be a waste to load them on pages without videos.<br>So I wrote a small partial to conditionally include these two resources only when needed.<br>That is, only pages or sections using the lite-youtube shortcode will load them.
head><br>...<br>{{ $hasYoutube := partial "conditional-youtube.html" . }}<br>{{ if $hasYoutube }}<br>{{ $ytCSS := resources.Get "lite-yt-embed.css" | minify | fingerprint }}<br>{{ $ytJS := resources.Get "lite-yt-embed.js" | minify | fingerprint }}<br>link rel="stylesheet" href="{{ $ytCSS.RelPermalink }}" integrity="{{ $ytCSS.Data.Integrity }}" ><br>script src="{{ $ytJS.RelPermalink }}" defer integrity="{{ $ytJS.Data.Integrity }}">script><br>{{ end }}<br>...<br>head>
{{ $hasYoutube := false }}<br>{{ $listTypes := slice "logs" "web-gems" }}
{{ if .IsPage }}<br>{{ $hasYoutube = .HasShortcode "lite-youtube" }}<br>{{ else if in $listTypes .Type }}<br>{{ range .Paginator.Pages }}<br>{{ if .HasShortcode "lite-youtube" }}<br>{{ $hasYoutube = true }}<br>{{ break }}<br>{{ end }}<br>{{ end }}<br>{{ end }}
{{ return $hasYoutube }}
Finally, the shortcode itself.<br>As I mentioned, playlists required a small workaround.<br>Since lite-youtube-embed expects a videoid, I manually provide one via poster-id for the thumbnail, while the shortcode handles passing the playlist ID as a parameter to the iframe.
{{ $src := .Get "src" }}<br>{{ $title := .Get "title" }}<br>{{ $posterQuality := .Get "poster-quality" | default "maxres" }}<br>{{ $customParams := .Get "params" }}
{{ $url := urls.Parse $src }}<br>{{ $v := $url.Query.Get "v" }}<br>{{ $list := $url.Query.Get "list" }}
{{ if not (or $v $list) }}<br>{{ erroridf "lite-youtube-invalid-url" "%s: Invalid YouTube URL: %s" .Position $src }}<br>{{ end }}
{{ $posterId := .Get "poster-id" | default $v }}<br>{{ $posterUrl := printf "https://i.ytimg.com/vi/%s/%sdefault.jpg" $posterId $posterQuality }}
{{ $queryParams := dict }}<br>{{ with $v }}{{ $queryParams = merge $queryParams (dict "v" .) }}{{ end }}<br>{{ with $list }}{{ $queryParams = merge $queryParams (dict "list" .) }}{{ end }}
{{ $path := cond $list "playlist" "watch" }}<br>{{ $query := querify $queryParams }}<br>{{ $href := printf "https://www.youtube.com/%s?%s" $path $query }}
{{ $params := slice }}<br>{{ with $list }}{{ $params = $params | append (printf "list=%s" .) }}{{ end }}<br>{{ with $customParams }}{{ $params = $params | append . }}{{ end }}<br>{{ $params = delimit $params "&" }}
div class="responsive-embed ratio-16-9"><br>lite-youtube<br>videoid="{{ $v }}"<br>title="{{ $title }}"<br>style="background-image: url('{{ $posterUrl }}');"<br>{{- with $params }}params="{{ . }}"{{- end }}><br>a href="{{ $href }}"<br>class="lyt-playbtn"<br>title="{{ i18n "play" }} YouTube"<br>aria-label="{{ i18n "play" }} YouTube {{ $title }}"><br>a><br>lite-youtube><br>div>
{{ partial "nojs.html" $src }}
∗ ∗ ∗<br>August 14, 2026<br>logs<br>computing<br>Comment by email ↪<br>Back to top ↑<br>License and Privacy, Contact, Support, RSS, twtxt<br>© 2018-2026 Eterno Devir .<br>Sensible simplicity.