youtube-player

Privacy-first YouTube embed with facade pattern. Zero iframe bytes until click — renders a thumbnail and play button, then swaps to the real player on interaction.

Overview

A lightweight YouTube embed that uses the facade pattern — renders a thumbnail image with a play button on page load, deferring the ~500 KB YouTube iframe until the user actually clicks play. Uses youtube-nocookie.com for privacy: no cookies are set until the user initiates playback.

Light DOM only (no shadow root), so design tokens and utility classes apply naturally.

Default

Provide a YouTube video ID via video-id and an accessible title via title.

<youtube-player video-id="dQw4w9WgXcQ" title="Rick Astley — Never Gonna Give You Up"> </youtube-player>

Rounded

Apply the rounded class (inherited from the <video> native element vocabulary).

<youtube-player class="rounded" video-id="dQw4w9WgXcQ" title="Rick Astley — Never Gonna Give You Up"> </youtube-player>

With Caption

Wrap in a <figure> with <figcaption> for a captioned embed.

<figure> <youtube-player class="rounded" video-id="dQw4w9WgXcQ" title="Rick Astley — Never Gonna Give You Up"> </youtube-player> <figcaption>Never Gonna Give You Up — Rick Astley (1987)</figcaption> </figure>

Playlist

Pass a YouTube playlist ID via list. YouTube manages the playlist UI inside the iframe.

<youtube-player video-id="dQw4w9WgXcQ" list="PLbpi6ZahtOH6Ar_3GPy3j-g4s4zu4jOeJ" title="Playlist example"> </youtube-player>

Start at Timestamp

Use start to begin playback at a specific second.

<youtube-player video-id="dQw4w9WgXcQ" start="30" title="Starts at 30 seconds"> </youtube-player>

Attributes

AttributeRequiredTypeDefaultDescription
video-idYesstringYouTube video ID
titleRecommendedstring"Play video"Accessible title for iframe and play button
startintegerStart playback at N seconds
liststringYouTube playlist ID
paramsstringRaw query string appended to embed URL (escape hatch)
autoplaybooleanfalseSkip facade — load iframe immediately
thumbnailstringhqThumbnail resolution: hq, mq, sd, maxres

Component-Managed Attributes

AttributeValuesDescription
stateready, activeFacade showing vs iframe loaded

CSS Classes

Inherited from the <video> native element vocabulary — no new classes invented.

ClassEffect
widescreen16:9 aspect ratio (default)
standard4:3 aspect ratio
ultrawide21:9 aspect ratio
roundedBorder radius via --radius-m token
fullinline-size: 100%

Progressive Enhancement

Author an <a> fallback inside the element. Without JavaScript, the link takes the user to YouTube. Once the component upgrades, the facade replaces the link.

<!-- Without JS: renders as a plain link to YouTube --> <youtube-player video-id="dQw4w9WgXcQ" title="Rick Astley — Never Gonna Give You Up"> <a href="https://youtu.be/dQw4w9WgXcQ"> Watch: Rick Astley — Never Gonna Give You Up </a> </youtube-player>
ScenarioBehaviour
No JSAnchor link to YouTube visible
JS loadedFacade: thumbnail + play button
User clicksIframe replaces facade, video autoplays
autoplayIframe rendered immediately — no facade step

Accessibility

  • Thumbnail image has alt="" (decorative — the button has the label)
  • Play button has aria-label="Play {title}"
  • Host element gets tabindex="0" and role="button" in facade state for keyboard access
  • Enter and Space activate the embed
  • After activation, focus moves to the iframe
  • Iframe has a descriptive title attribute
  • No-JS fallback is a plain anchor with meaningful text
  • No animations that violate prefers-reduced-motion

Performance

MetricValue
JS size< 2 KB
CSS size< 1 KB
Network requests before click1 (thumbnail image only)
YouTube cookies before clickNone (youtube-nocookie.com)

Related

  • <video-player> — Self-hosted video with custom overlay controls
  • <video> — Native video element (aspect-ratio classes shared with this component)
  • <iframe> — Native iframe element