Frontend Development 11 min read

Document Picture-in-Picture API: Full Tutorial and Implementation Guide

This article provides a comprehensive tutorial on the Document Picture-in-Picture (PiP) API, covering its purpose, browser support checks, window creation, style synchronization, event handling, cloning techniques, and a complete example with HTML, CSS, and JavaScript code.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Document Picture-in-Picture API: Full Tutorial and Implementation Guide

Document Picture-in-Picture Introduction

The Document Picture-in-Picture (PiP) API allows any HTML content to be displayed in a floating window that stays on top of the screen, similar to video PiP but applicable to arbitrary elements.

Video PiP vs. Document PiP

Traditional video PiP works on platforms like Tencent Video and Bilibili, but Document PiP extends this capability to any DOM element, enabling flexible UI interactions.

Basic HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document Picture-in-Picture API 示例</title>
    <style>
        #pipContent {
            width: 600px;
            height: 300px;
            background: pink;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="pipContent">这是一个将要放入画中画的 div 元素!</div>
        <button id="clickBtn">切换画中画</button>
    </div>
    <script>
        // JavaScript will be added here
    </script>
</body>
</html>

Requesting a PiP Window

The core method is window.documentPictureInPicture.requestWindow , which returns a Promise that resolves to a new window object representing the PiP window.

document.getElementById("clickBtn").addEventListener("click", async function () {
    const pipContent = document.getElementById("pipContent");
    const pipWindow = await window.documentPictureInPicture.requestWindow({
        width: 200,
        height: 300
    });
    pipWindow.document.body.appendChild(pipContent);
});

Checking Browser Support

if ('documentPictureInPicture' in window) {
    console.log("🚀 浏览器支持 PiP 功能!");
} else {
    console.warn("⚠️ 当前浏览器不支持 PiP 功能,更新浏览器或者换台电脑吧!");
}

Synchronizing Styles

To make the PiP window look the same as the original page, copy all stylesheet rules or link tags into the PiP document.

// Copy CSS rules
[...document.styleSheets].forEach((styleSheet) => {
    try {
        const cssRules = [...styleSheet.cssRules].map(rule => rule.cssText).join('');
        const style = document.createElement('style');
        style.textContent = cssRules;
        pipWindow.document.head.appendChild(style);
    } catch (e) {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = styleSheet.type;
        link.media = styleSheet.media;
        link.href = styleSheet.href ?? '';
        pipWindow.document.head.appendChild(link);
    }
});

Event Listeners for PiP

Listen for entering and exiting PiP, as well as focus/blur events.

// Enter event
documentPictureInPicture.addEventListener("enter", () => {
    console.log("已进入 PIP 窗口");
});
// Exit event
pipWindow.addEventListener("pagehide", () => {
    console.log("已退出 PIP 窗口");
});
// Focus / blur
pipWindow.addEventListener('focus', () => {
    console.log("PiP 窗口进入了焦点状态");
});
pipWindow.addEventListener('blur', () => {
    console.log("PiP 窗口失去了焦点");
});

Cloning Elements

To keep the original element visible, clone it before appending to the PiP window.

const pipContent = document.getElementById("pipContent");
const pipWindow = await window.documentPictureInPicture.requestWindow({width:200,height:300});
pipWindow.document.body.appendChild(pipContent.cloneNode(true));

Complete Example

The full working example combines all the above steps into a single HTML file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document Picture-in-Picture API 示例</title>
    <style>
        #pipContent { width:600px; height:300px; background:pink; font-size:20px; }
    </style>
</head>
<body>
    <div id="container">
        <div id="pipContent">这是一个将要放入画中画的 div 元素!</div>
        <button id="clickBtn">切换画中画</button>
    </div>
    <script>
        if ('documentPictureInPicture' in window) {
            console.log("🚀 浏览器支持 PiP 功能!");
        } else {
            console.warn("⚠️ 当前浏览器不支持 PiP 功能,更新浏览器或者换台电脑吧!");
        }
        document.getElementById("clickBtn").addEventListener("click", async function () {
            const pipContent = document.getElementById("pipContent");
            const pipWindow = await window.documentPictureInPicture.requestWindow({width:200,height:300});
            pipWindow.document.body.appendChild(pipContent.cloneNode(true));
            // Sync styles
            [...document.styleSheets].forEach((styleSheet) => {
                try {
                    const cssRules = [...styleSheet.cssRules].map(r=>r.cssText).join('');
                    const style = document.createElement('style');
                    style.textContent = cssRules;
                    pipWindow.document.head.appendChild(style);
                } catch(e) {
                    const link = document.createElement('link');
                    link.rel='stylesheet';
                    link.type=styleSheet.type;
                    link.media=styleSheet.media;
                    link.href=styleSheet.href ?? '';
                    pipWindow.document.head.appendChild(link);
                }
            });
            // Events
            pipWindow.addEventListener('pagehide',()=>{console.log('已退出 PIP 窗口');});
            pipWindow.addEventListener('focus',()=>{console.log('PiP 窗口进入了焦点状态');});
            pipWindow.addEventListener('blur',()=>{console.log('PiP 窗口失去了焦点');});
        });
    </script>
</body>
</html>

Conclusion

By following this guide, you can leverage the Document Picture-in-Picture API to float any HTML element, synchronize its styles, and handle lifecycle events, enabling richer interactive experiences on modern browsers.

frontendJavaScripthtmlWeb APIDocument Picture-in-Picturepip
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.