DEV Community

Cover image for PiP - videos in a floating window
Mahmoud Elmahdi
Mahmoud Elmahdi

Posted on

PiP - videos in a floating window

I used to watch conferences, DIY tutorials, a new piece of tech review or even a standup comedy videos in a floating mini player playing down there in the corner on top of the other windows while interacting with other tasks like writing code, an article, or reading reddit, twitter or hacker news.

As far as I know there's a pretty awesome extensions for both of Chrome and Safari that handle such a thing for YouTube videos. This can be done with a JavaScript/Web API!

Picture-in-Picture Web API

Picture-in-Picture (PiP) is a common platform-level feature among desktop and mobile OSs. Picture-in-Picture (PiP) allows users to watch videos in a floating window (always on top of other windows) so they can keep an eye on what they’re watching while interacting with other tasks. This window stays visible even when user agent is not visible.

The specification aims to allow websites to initiate and control this behavior by exposing the following sets of properties to the API:

  • Notify the website when it enters and leave Picture-in-Picture (floating) mode.
  • Allow the website to trigger Picture-in-Picture via a user gesture on a video element.
  • Allow the website to know the size of Picture-in-Picture window and notify the website when it changes.
  • Allow the website to exit Picture-in-Picture.
  • Allow the website to check if Picture-in-Picture can be triggered.


Check if Picture-in-Picture is supported and available:

const isPiPAvailable = () => {
    return document.pictureInPictureEnabled || !videoElement.disablePictureInPicture;

isPiPAvailable() ? showPiPButton() : hidePiPButton();
Enter fullscreen mode Exit fullscreen mode

The Picture-in-Picture Web API may not be supported, so we have to detect this to provide progressive enhancement. Even when it is supported, it may be turned off by the user or disabled by a feature policy. Luckily, you can use the new boolean document.pictureInPictureEnabled to determine this.

Request or exist Picture-in-Picture:

try {
    if (!document.pictureInPictureElement) {
    } else {
} catch(reason) {
Enter fullscreen mode Exit fullscreen mode
  • If Picture-in-Picture support is false, throw a NotSupportedError
  • If document is not allowed to use the policy-controlled feature named "picture-in-picture", throw a SecurityError
  • If the disablePictureInPicture attribute is present on video, throw a InvalidStateError

Monitor video Picture-in-Picture changes:

// Video entered Picture-in-Picture mode.
video.addEventListener('enterpictureinpicture', (event) => console.log(event))
// Video left Picture-in-Picture mode.
video.addEventListener('leavepictureinpicture', (event) => console.log(event))
Enter fullscreen mode Exit fullscreen mode

Listen to Picture-in-Picture events instead of waiting for promises to update your media player controls. It's possible for the video to enter and exit Picture-in-Picture at any time (e.g. user clicks some browser context menu or Picture-in-Picture is triggered automatically). User may have played a Picture-in-Picture video from a different page.

MediaStream video support

Video playing MediaStream objects (e.g. getUserMedia(), getDisplayMedia(), canvas.captureStream()) also support Picture-in-Picture in Chrome 71. This means you can show a Picture-in-Picture window that contains user's webcam video stream, display video stream, or even a canvas element. Note that the video element doesn't have to be attached to the DOM to enter Picture-in-Picture.

Picture-in-Picture Demo

Check out sample demo here

Security considerations

The API applies only to HTMLVideoElement in order to start on a minimal viable product that has limited security issues. Later versions of this specification may allow PIP-ing arbitrary HTML content.

Feature Policy

This specification defines a policy-controlled feature that controls whether the request Picture-in-Picture algorithm may return a SecurityError and whether pictureInPictureEnabled is true or false.


Discussion (0)