GuidePlayback
Use picture-in-picture
Pop the video into a floating window, with availability detection and state that tracks every entry path.
Recommended approach
Add a <media-pip-button>. It requests and exits picture-in-picture, reflects the current state, and stays hidden until picture-in-picture is available.
How it works
The picture-in-picture feature puts three things in player state.
isPictureInPicture is true while the video is in a floating window. It tracks every way in and out — your button, the native controls, or a control the browser adds on its own.
pictureInPictureAvailability starts as 'unavailable'. It becomes 'available' when the media supports picture-in-picture and has loaded metadata, or 'unsupported' when the browser or media has no supported route. Loading a new source returns it to 'unavailable' until metadata loads.
requestPictureInPicture() and exitPictureInPicture() change the presentation. Handle rejected promises when the browser blocks a request. An entry request before metadata loads rejects with InvalidStateError. Without a supported API, the request resolves without opening a window.
Picture-in-picture and fullscreen are exclusive: requesting one exits the other first.
Availability and constraints
If a Safari standalone web app exposes the standard Picture-in-Picture API, Video.js still reports picture-in-picture as 'unsupported'. The built-in button hides in that case. Check pictureInPictureAvailability in installed web apps as well as browser tabs.
- Show picture-in-picture controls only when
pictureInPictureAvailabilityis'available'.<media-pip-button>handles this for you. - Requests must come from a user gesture; browsers reject requests outside one.
- Firefox 153 (July 2026) added the programmatic picture-in-picture API on desktop. On earlier desktop versions, including Firefox ESR 140,
pictureInPictureAvailabilityis'unsupported', even though Firefox shows users its own picture-in-picture toggle. CheckpictureInPictureAvailabilityrather than inferring support from the browser version. - On iOS, picture-in-picture is supported on iPhone and iPad through the WebKit presentation mode; the player handles this path for you.
- The browser owns the floating window: its size, position, and built-in controls aren’t yours to style.
- The user can close the window or return the video at any time. React to
isPictureInPictureinstead of assuming your button is the only entry and exit.
Common variations
Open picture-in-picture from your own button
Call requestPictureInPicture() directly in your button’s click handler so the browser treats the request as a user gesture. The action exits fullscreen first, then uses the standard Picture-in-Picture API or Safari’s presentation mode:
Troubleshooting
The picture-in-picture button doesn’t render
Check pictureInPictureAvailability. It is 'unavailable' before metadata loads, and 'unsupported' when the browser or media has no supported picture-in-picture route. Some embeds cannot enter picture-in-picture even in a browser that supports it.
The request rejects
The request ran outside a user gesture, or the browser refused it. Handle the rejection. A request before metadata loads rejects with InvalidStateError; check pictureInPictureAvailability before offering your button.
State is wrong after the user closes the floating window
Read isPictureInPicture from player state instead of tracking entry and exit yourself; it stays in sync with every path in and out of picture-in-picture.