Skip to content
FrameworkStyle

Add a poster placeholder

Show a lightweight placeholder while the poster image loads

To show something while your video’s poster loads, customize the image drawn by the skin or the Poster component.

The examples keep the placeholder aligned with the poster position. Change contain to cover if your poster fills its container.

Use a framework image component

Many frameworks have image components that render both an image and a placeholder while it loads. Pass one to renderPoster; it receives src from Video.js when the media provides a poster.

import NextImage from 'next/image';
import type { ComponentProps } from 'react';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer, VideoSkin } from '@videojs/react/video';

export function MyPlayer() {
  return (
    <VideoPlayer>
      <VideoSkin
        renderPoster={({ src, ...props }: ComponentProps<'img'>) =>
          src ? (
            <NextImage
              {...props}
              src={src}
              alt=""
              fill
              placeholder="blur"
              blurDataURL="data:image/webp;base64,…"
            />
          ) : null
        }
      >
        <MuxVideo
          source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
          playsInline
        />
      </VideoSkin>
    </VideoPlayer>
  );
}

Next.js generates blur data for static imports. Because this poster URL arrives at runtime, pass blurDataURL yourself.

Use a plain image

A background image on the poster works well for a lightweight placeholder:

import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer, VideoSkin } from '@videojs/react/video';

export function MyPlayer() {
  return (
    <VideoPlayer>
      <VideoSkin
        renderPoster={(props) => (
          <img
            {...props}
            style={{
              ...props.style,
              background:
                "url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat",
            }}
          />
        )}
      >
        <MuxVideo
          source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
          playsInline
        />
      </VideoSkin>
    </VideoPlayer>
  );
}

Use the Poster component

If you built your own UI, use the same render prop directly on Poster:

import { Container, Poster } from '@videojs/react';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer } from '@videojs/react/video';

export function MyPlayer() {
  return (
    <VideoPlayer>
      <Container style={{ position: 'relative', aspectRatio: '16 / 9' }}>
        <MuxVideo
          source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
          playsInline
        />
        <Poster
          render={(props) => (
            <img
              {...props}
              style={{
                ...props.style,
                position: 'absolute',
                inset: 0,
                width: '100%',
                height: '100%',
                background:
                  "url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat",
                objectFit: 'contain',
              }}
            />
          )}
        />
      </Container>
    </VideoPlayer>
  );
}