Tags: web-dev concept

Video and Media

Date: 2026-08-17


Video is the heaviest thing most retail sites ship, and the default <video> attributes are wrong for nearly every use of it. The two decisions that matter are what downloads before anyone presses play, and whether the thing is a video at all.


Video delivery is how video reaches the page — the <video> element’s loading attributes, the file’s encoding, and whether it streams adaptively — which decides what downloads, when, and how much.

The attributes, and what the defaults cost

<!-- an autoplaying background or product loop -->
<video
  poster="/product-loop.avif"   <!-- shown before playback; also the LCP
                                     candidate, so optimise it as an image -->
  preload="none"                <!-- ← the important one. see below -->
  autoplay muted playsinline loop
  width="1280" height="720">    <!-- reserves space, prevents layout shift -->
  <source src="/loop.webm" type="video/webm">
  <source src="/loop.mp4"  type="video/mp4">
</video>

preload is where the weight goes, and the default is the problem:

preload="none"        fetches nothing until play. metadata unknown.
                      ← the right default for anything below the fold
                        or click-to-play

preload="metadata"    fetches duration and dimensions only, a few KB
                      ← sensible when you need the duration displayed

preload="auto"        the browser MAY fetch the whole file
                      ← on a 24 MB product video, before anyone
                        pressed play. this is the accident

autoplay requires muted — browsers block autoplay with sound, and a video that silently fails to play is a common bug. playsinline prevents iOS taking over the screen, which is essential for a background loop.

The one that isn’t really a video

Most “videos” on retail sites are silent, short, looping and decorative — a fabric close-up, a garment moving, a product rotating. For these, the format question is upstream of everything else:

animated GIF          ✗ enormous. a 3-second loop is often 4–8 MB.
                        never correct in 2026

animated WebP/AVIF    better, still image-codec compression

MUTED LOOPING VIDEO   ✓ 10–20× smaller than the equivalent GIF
  (WebM/MP4)            video codecs exist for exactly this

CSS/SVG animation     ✓ best of all, where the motion is simple

Replacing an animated GIF with a muted MP4 loop is one of the largest single-file wins available on sites that still have them, and it’s a mechanical change — Modern Image Formats.

Streaming, and when it’s worth it

PROGRESSIVE (a plain .mp4)          ADAPTIVE
                                    HLS  — HTTP live streaming
                                    DASH — dynamic adaptive streaming over HTTP

one file, one bitrate               many renditions, segmented
served from any static host         needs a packager and a manifest
simple, cacheable                   player library required (~50–100 KB JS)

user on a poor connection buffers   player switches down automatically
user on fibre gets the same file    fast connections get a better rendition

fine for: short loops, <30s          worth it for: long-form, >2 min,
  clips, anything under ~10 MB         or a video that's the point of
                                       the page

Adaptive streaming has a real fixed cost — the player JavaScript, the packaging pipeline, the manifest. For a 6-second product loop it’s absurd; for a 4-minute brand film it’s the difference between watchable and abandoned.

Prefer a hosted video service for anything long-form. Encoding ladders, adaptive delivery, DRM and global distribution are not worth building — and this is a rare case where the vendor’s version is straightforwardly better than what you’d assemble.

What it does to the metrics

  • The poster frame is often the LCP element. It’s an image, so all of Image Optimisation applies — right dimensions, modern format, not lazy-loaded
  • Video itself is usually not the LCP element, so a heavy video hurts by consuming bandwidth that the LCP resource needed, rather than by being slow itself
  • Always set width and height, or the player collapses to zero height and expands on load — Cumulative Layout Shift
  • Autoplaying video competes for the main thread on decode, which affects interaction responsiveness on lower-end devices — Interaction to Next Paint
  • Lazy-load below-fold video — preload="none" plus loading the player only when it scrolls near the viewport — Lazy Loading

Embedded third-party players

A YouTube or Vimeo embed is a third-party iframe that loads a substantial amount of JavaScript, sets cookies and runs before anyone has expressed interest in watching.

The facade pattern is the fix: render the poster image and a play button as plain HTML, and only inject the real embed on click.

default embed          ~500 KB–1 MB, third-party cookies set on load
facade                 ~30 KB (one image), embed loads on click only

Consent applies here too — an embed that sets tracking cookies before consent is a compliance problem as well as a performance one — Consent Management, Third-Party Scripts.

Accessibility, which isn’t optional

  • Captions for anything with speech — a <track kind="captions"> element, not burnt-in text
  • A transcript for long-form, which also serves SEO
  • Never autoplay with sound, and provide a pause control for anything looping
  • Respect prefers-reduced-motion — an autoplaying background loop is exactly what that setting exists for, and honouring it means not playing rather than playing slower — Reduced Motion, WCAG

Where it interacts

  • Image Optimisation — the poster frame is an image and usually the LCP element
  • Lazy Loading — the main mitigation for below-fold media weight
  • Third-Party Scripts — embedded players are among the heaviest third parties on a typical page
  • Reduced Motion — the accessibility constraint on anything that moves without being asked to