player icon indicating copy to clipboard operation
player copied to clipboard

Missing Poster attribute on Video Element

Open felipehertzer opened this issue 10 months ago • 9 comments

Current Behavior:

The MediaPlayer component does not apply the poster attribute to the underlying <video> element. This prevents the poster image from being displayed when using MediaPlayer to play an audio file.

  • Adding the poster attribute to MediaPlayer does not result in the <video> element receiving it.
  • As a result, the expected poster image is not displayed.
  • If controls is set on MediaPlayer, the poster appears, but this replaces the Vidstack controls with the browser’s default controls.

Expected Behavior:

  • The poster attribute should be correctly applied to the <video> tag when set on MediaPlayer.
  • The poster image should be visible when playing an audio file.
  • Vidstack’s custom controls should remain functional.

Steps To Reproduce:

  1. Use MediaPlayer with the poster attribute.
  2. Play an audio file.
  3. Inspect the <video> element and observe that the poster attribute is missing.
<MediaPlayer
  ref={player}
  src={mp3File}
  viewType="video"
  poster={mediaThumbnail}
/>

Environment:

  • Framework: React
  • Meta Framework: Vite
  • Node: 22
  • Device: MacBook Pro M4
  • OS: macOS Sonoma
  • Browser: Chrome 133

Anything Else?

<video  aria-hidden="true" preload="metadata">
<source src="file.mp3" type="video/mp4" data-vds="">
</video>
<img class="vds-poster" style="pointer-events: none;" src="image.jpg">

Should be

<video  aria-hidden="true" preload="metadata" poster="image.jpg">
<source src="file.mp3" type="video/mp4" data-vds="">
</video>
<img class="vds-poster" style="pointer-events: none;" src="image.jpg">

felipehertzer avatar Feb 14 '25 09:02 felipehertzer

+1, we just ran into the same issue.

joshsedl avatar Apr 01 '25 14:04 joshsedl

I can confirm the same for videos, not only audio, using the data-poster attribute in vanilla JS.

JPustkuchen avatar Apr 01 '25 15:04 JPustkuchen

+1, same issue here with react

blueskoo avatar Apr 04 '25 09:04 blueskoo

Has anyone found a solution to this?

garrettsiegel avatar Aug 11 '25 14:08 garrettsiegel

I'm using with the uppercase P, it works, but typescript complains about it.

Poster={mediaThumbnail}

felipehertzer avatar Aug 11 '25 21:08 felipehertzer

+1 React

rjmoggach avatar Aug 18 '25 02:08 rjmoggach

submitted a pull request... obviously tweak, change, edit, clean up...

Files:

  1. /packages/vidstack/src/elements/define/provider-element.ts - Line 121 (but this wasn't the actual issue for React apps)
  2. /packages/react/src/components/provider.tsx - Line 171 (this was the real fix for me/react)

rjmoggach avatar Aug 18 '25 16:08 rjmoggach

Are there any work arounds ahead of the PR being merged?

garyfagan-commits avatar Aug 20 '25 14:08 garyfagan-commits

@garyfagan-commits Just implemented a (dirty) workaround using an img and some CSS.

<div class="media-video-vidstack-poster-workaround">
  <div class="media-video-vidstack-poster-workaround__poster"><img src="poster_xy.webp"></div>
  <div class="media-video-vidstack-poster-workaround__vidstack-wrapper"><!-- Vidstack Player --></div>
</div>

And the CSS:

.media-video-vidstack-poster-workaround {
  --poster-opacity: 1;
  position: relative;
  line-height: 1;
}
.media-video-vidstack-poster-workaround__poster {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  transition-duration: 80ms;
  transition-property: opacity;
  opacity: var(--poster-opacity);
  img {
    object-fit: cover;
    object-position: center;
    max-width: none;
    height: 100%;
    width: 100%;
  }
}
.media-video-vidstack-poster-workaround:has([data-started]) {
  --poster-opacity: 0;
}

Result:

Image

thomasfrobieter avatar Oct 17 '25 13:10 thomasfrobieter