Search code examples
htmlvideovideo-streaminghtml5-videomedia

How to embed a video background on a website (fast, loop, autoplay)


On my website, I want a fullscreen video playing in the background.

Note, that I already found related questions and answers (e.g. 1, 2. 3), but they only provide a partial solution to my question.

At first, I was using the HTML5 <video> tag to directly load the video from my server, but it took very long to load. Even when tweaking the file size using different resolutions and compression settings, I still had around 50MB of data to load.

Do you have any recommendations on how to achieve this? I assume there are solutions with streaming platforms (like YouTube) but I couldn't find the information I need.

The following aspects are essential to me:

  • The video should ideally load instantly
  • Autoplay
  • Loop endlessly
  • Audio is not required
  • No distractions like controls, icons, or progress bars
  • Ideally, additional styles can be applied (e.g. a grayscale filter)

Solution

  • There are pros and cons to using <video> over a streaming approach.

    The issue with using <video>

    The biggest issue here is the requirement to load the complete video. Only when the final frame is available, the video can start. Even though you can use the poster parameter to show an image until the video is fully loaded, this waiting time pretty much ruins the first impression for your users.

    You should definitely try again to generate a compressed version of your video. Take a look at the WebM file format, here you can realize very low file sizes.

    The benefit of using a native <video> on your website

    Especially on mobile, you will notice problems with playing a YouTube video in the background. Often, the video doesn't play unless the user interacts with it (i.e. taps on the play button). So it's again not a satisfying experience for your users, which is why you should try using <video> instead.

    The benefits of streaming a video

    Streaming a video allows the user to start watching even though it is not completely available yet. Also, depending on the device's network speed and display size, the video is delivered with a tailored resolution and compression, making it even more efficient to load. Just imagine YouTube without this behavior, it would be completely unusable.

    In the end, it's all about reducing page load time. Here is a great article that explains why this is so important: https://web.dev/fast/

    But, as explained above already, the behavior on mobile devices could be a deal breaker, because of the required user interaction with the video.

    How to: Embed a YouTube video in an <iframe>

    Even though there are framework-specific solutions available (just search for "embed youtube" on GitHub), you could have a plain old but gold <iframe> that loads your video hosted on YouTube.

    All available parameters are described here: https://developers.google.com/youtube/player_parameters

    Here is an example for your use case (not using a snippet here because it doesn't load the content from YouTube):

    <iframe 
      class="bg-video"
      src="https://www.youtube.com/embed/dQw4w9WgXcQ?autoplay=1&mute=1&controls=0&loop=1&playlist=dQw4w9WgXcQ"
      frameBorder="0"
      allowFullScreen
      allow="autoplay"
    />
    

    Note the URL parameters that are used here.

    parameter meaning
    ?autoplay=1 Start video automatically
    &mute=1 Video without audio
    &controls=0 Hide the progress bar and other YouTube UI elements
    &loop=1 Play video in a loop. requires another parameter below.
    &playlist=dQw4w9WgXcQ As described in the docs, you have to provide the video ID in the playlist parameter to make looping work - for whatever reason.

    Experiment with some CSS styles to get the perfect display you wish (also using code from this solution):

    .bg-video {
      position: fixed;
      left: 0;
      top: 0;
      background-size: cover;
      background: no-repeat center;
      margin-left: 50vw;
      user-select: none;
      pointer-events: none;
    
      /*custom styles, for example grayscale appearance*/
      filter: grayscale(0.8);
    
      /*additional tweaks for positioning, read more in the link above*/
      height: 100%;
      width: 177.77777778vh; /* 100 * 16 / 9 */
      min-width: 100%;
      min-height: 56.25vw; /* 100 * 9 / 16 */
    }
    
    
    

    And here is a demo of the result (long live the king):

    demo