Recreating Spotify’s Floating pop-ups

Recreating Spotify’s Floating pop-ups

A look at the Picture In Picture API
Ferenc AlmasiLast updated 2021 November 11 • Read time 4 min read
Get your weekly dose of webtips
  • twitter
  • facebook
JavaScript

Recently I had come in contact with the Picture In Picture API that is also used on Spotify to pop out the currently playing song into a separate window.

If you have no idea what I’m talking about, there’s a little button inside Spotify’s web app that resembles a screen. If you click on this button, a window will pop up that is completely separate from the browser. It can overlay other tabs and work independently from the tab it is launched from, so users can keep streaming content while browsing other sites or using other applications.

Opening the picture in picture overlay on spotify
Using the PiP button in Spotify will pop up a new window

What is The Picture in Picture API?

Picture-in-Picture is a new API that allows users to play and view video elements in a completely separate overlay from the main browser. Its main purpose is to enable users to consume content from one website while they are surfing the web or using other applications.

It’s been with Android since the spring of 2017 but is coming to the web and you can already use it in Chrome and partially supported in Firefox and Safari. For the full list of browser support, you can refer to the table on caniuse.


How Can I Use It?

For the tutorial, I’ve created this small snippet:

Copied to clipboard! Playground
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Picture in Picture</title>
    <link rel="stylesheet" href="styles.css" />
</head>
<body>
    <div id="app">
        <video class="video" src="video.mp4" controls></video>
        <div class="controls">
            <img class="toggle-pic-in-pic" src="picinpic.svg" alt="" />
        </div>
    </div>

    <script src="app.js"></script>
</body>
</html>
index.html

Nothing fancy going on, we have a video tag and a control which will trigger the picture in picture API.

After applying some styles, this is how it looks in the browser:

Initial state of the app

You will notice that if you click on the three dots in the controls of the video, you already have an option to open it in picture in picture. To outsource this behavior and make other buttons on the page act as a pop-up button, add the following event listener to the icon:

Copied to clipboard! Playground
const video = document.querySelector('.video');
const pipButton = document.querySelector('.toggle-pic-in-pic');

pipButton.addEventListener('click', event => {
    if (video !== document.pictureInPictureElement) {
        video.requestPictureInPicture();
    } else {
        document.exitPictureInPicture();
    }
});
app.js

It’s important to note that only video elements can be requested to enter into PiP mode. But first, we need to test if an element is already in PiP mode. document.pictureInPictureElement will return the element that is currently in PiP mode, otherwise it will return null. Before requesting new elements to be promoted into PiP mode, you need to close already running ones.

Picture in Picture mode shown on tab
Picture in Picture mode will also show up on tab

We can also listen for multiple events, such as entering, leaving, or resizing the window:

Copied to clipboard! Playground
let pipWindow = null;
let resizeEvent = () => console.log(`window resized to ${pipWindow.width}x${pipWindow.height}`);

video.addEventListener('enterpictureinpicture', event => {
    console.log('Video is in Picture-in-Picture mode');

    pipWindow = event.pictureInPictureWindow;

    pipWindow.addEventListener('resize', resizeEvent);
});
  
video.addEventListener('leavepictureinpicture', event => {
    console.log('Video leaving Picture-in-Picture mode');

    pipWindow.removeEventListener('resize', resizeEvent);
});
app.js

Lastly, to avoid getting errors, you need to test first whether your browser supports the API. To do so you can simply check for the pictureUnPictureEnabled property on the window.

Copied to clipboard! Playground
if ('pictureInPictureEnabled' in document) {
    pipButton.hidden = false;
} else {
    pipButton.hidden = true;
}
app.js
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScriptinfo Remove ads

The End Result

Now you can stream content to users even when they leave your site. (the tab must be kept open though) Trying to open a new element will terminate the previous one first.

Picture in Picture element in use
The picture in picture element stays on top even when switched to other applications
  • twitter
  • facebook
JavaScript
Did you find this page helpful?
📚 More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.