Skip to content

Embed YouTube Videos

1 min read

This guide leads you embed YouTube videos in Starlight/Astro.

  1. Start by installing the lite-youtube-embed package using your favorite package manager:

    Terminal window
    npm add lite-youtube-embed
  2. Create YouTube.astro in src/components:

    src/components/YouTube.astro
    ---
    // Source code from astro-embed-youtube: https://github.com/delucis/astro-embed/tree/main/packages/astro-embed-youtube
    import 'lite-youtube-embed/src/lite-yt-embed.css'
    export interface Props extends astroHTML.JSX.HTMLAttributes {
    id: string
    poster?: string
    params?: string
    playlabel?: string
    }
    const { id, poster, ...attrs } = Astro.props as Props
    const urlPattern =
    /(?=(\s*))\1(?:<a [^>]*?>)??(?=(\s*))\2(?:https?:\/\/)??(?:w{3}\.)??(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/|shorts\/)??([A-Za-z0-9-_]{11})(?:[^\s<>]*)(?=(\s*))\4(?:<\/a>)??(?=(\s*))\5/
    function urlMatcher(url: string): string | undefined {
    const match = url.match(urlPattern)
    return match?.[3]
    }
    const idRegExp = /^[A-Za-z0-9-_]+$/
    function extractID(idOrUrl: string) {
    if (idRegExp.test(idOrUrl)) return idOrUrl
    return urlMatcher(idOrUrl)
    }
    const videoid = extractID(id)
    const posterURL = poster || `https://i.ytimg.com/vi/${videoid}/hqdefault.jpg`
    ---
    <lite-youtube
    {videoid}
    {...attrs}
    style={`background-image: url('${posterURL}');`}></lite-youtube>
    <script>
    import 'lite-youtube-embed'
    </script>
    <style is:global>
    lite-youtube > iframe {
    all: unset !important;
    width: 100% !important;
    height: 100% !important;
    position: absolute !important;
    inset: 0 !important;
    border: 0 !important;
    }
    </style>

Now, you can import it into your project inside any .astro/mdx file. For example:

import YouTube from 'import YouTube from '@/components/YouTube.astro';
<YouTube
id="_NIpfrGXwG8"
poster="https://i3.ytimg.com/vi/_NIpfrGXwG8/maxresdefault.jpg"
/>

The code above generates the following on the page: