poster-child
poster-child
is a teeny tiny niche script that lazy loads <video>
element poster
images. An image loaded by the poster
attribute is used for videos that do not autoplay, but need an image placeholder to display without loading the entire video or even its metadata.
Table of contents
Why lazy load <video>
element poster
images?
It's a niche thing, for sure, but it counts as a kind of media that can be data intensive. The web platform now supports native lazy loading for <img>
, <picture>
, and <iframe>
elements, but not for poster
images. This script allows you to do that, which can be useful if your website has a lot of non-autoplaying video content.
How do I use poster-child
?
Using poster-child
effectively means following the proper markup pattern and then invoking the script. Let's start with the <video>
markup you'll need to use.
Proper <video>
markup
To use poster-child
, you'll need to use the following pattern in your <video>
elements:
<video data-poster="poster.jpg" controls preload="none" width="320" height="240">
<source src="video.mp4" type="video/mp4">
</video>
The required parts of the markup for poster-child
to function are:
- A
data-poster
attribute pointing to the placeholder image to be lazy loaded. - The
controls
element, since a video with a poster
element should not be an autoplaying video. - No inclusion of an
autoplay
attribute under no circumstances. Even an autoplay
attribute with a value of "false"
will still autoplay video in some browsers. - A
preload
value of none
to avoid loading any of the video up front.
Any other use cases are not a fit for a poster
element to be used, let alone poster-child
.
Script usage
There's a few ways you can use poster-child
. You can install it from npm if you want:
npm i poster-child --save
Then in your application code, you can invoke it like so:
import { posterChild } from "poster-child";
posterChild();
This usage in concert with a bundler is preferred, as you'll get optimized production code. However, if you're the type to use a CDN, you can use it as a module:
<script>
import("https://unpkg.com/poster-child@0.1.0/dist/poster-child.modern.js").then(({ posterChild }) => {
posterChild();
});
</script>
If you don't use a package manager or don't want to use a CDN, grab this script (or any other version that suits your needs) from the dist
folder.
Options
poster-child
offers the following options you can send as an object to the initialzing posterChild
function:
posterChild({
context: "body",
observeChanges: false,
observerContext: "body"
});
In detail, these options offer the following:
context
: The context in which elements that match a selector of video[data-poster]
are selected. The default context is the <body>
element, but you can set this to only affect a portion of the page. The default means that elements matching body video[data-poster]
are selected.observeChanges
: whether or not to use a mutation observer. By default, poster-child
will only lazy load placeholder images that are present in markup during startup, but you can set this option to true
to capture any video[data-poster]
elements that are added to the DOM later on.observerContext
: Works just like context
, but is the context for the mutation observer. The default means that elements match body video[data-poster]
are observed.
Caveats
Aside from ensuring that your video markup is correct, there are some caveats you'll need to keep in mind.
Do you need more JavaScript?
poster-child
is very efficient and small. It relies on no framework code, and uses only web platform APIs. That said, don't include this unless your use case supports including it.
Efficient usage
By default, poster-child
only observes video[data-poster]
elements that are present in markup sent by the server. While you can use a mutation observer to observe video[data-poster]
elements that are added to the DOM later by JavaScript (such as an SPA might), only do so if you absolutely need to.
The reason for this is that when all of the video[data-poster]
elements have their image placeholders lazy loaded, the intersection observer that observes them will be disposed of. However, if observeChanges
is set to true
, this will never happen. It's a small detail, but an important one to keep in mind so your page introduces as little JavaScript activity as possible.
Avoid suboptimal lazy loading patterns
Browsers use an optimization called a preload scanner to opportunistically fetch resources that the primary HTML parser may be delayed from finding by parser and render blocking operations.
You should avoid using poster-child
to lazy load poster
images for <video>
elements that are in the viewport during git s, because the browser preload scanner will not be able to detect the poster
image as early as possible, causing a delay in rendering an image that should be eagerly loaded. <video>
elements with poster
images are candidates for LCP, which means this suboptimal pattern can raise your LCP in both the lab and the field.
Is that all?
Yeah.