惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
The Last Watchdog
The Last Watchdog
S
Security @ Cisco Blogs
Help Net Security
Help Net Security
Security Archives - TechRepublic
Security Archives - TechRepublic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
W
WeLiveSecurity
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Hacker News: Front Page
人人都是产品经理
人人都是产品经理
aimingoo的专栏
aimingoo的专栏
Vercel News
Vercel News
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
Project Zero
Project Zero
T
Tailwind CSS Blog
V
Vulnerabilities – Threatpost
P
Privacy & Cybersecurity Law Blog
Know Your Adversary
Know Your Adversary
Last Week in AI
Last Week in AI
腾讯CDC
Schneier on Security
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
量子位
L
Lohrmann on Cybersecurity
J
Java Code Geeks
Cyberwarzone
Cyberwarzone
Recent Announcements
Recent Announcements
IT之家
IT之家
博客园_首页
罗磊的独立博客
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Application and Cybersecurity Blog
Application and Cybersecurity Blog
F
Fortinet All Blogs
博客园 - Franky
P
Palo Alto Networks Blog
V2EX - 技术
V2EX - 技术
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Martin Fowler
Martin Fowler
N
News and Events Feed by Topic
C
Cybersecurity and Infrastructure Security Agency CISA
B
Blog RSS Feed
Cisco Talos Blog
Cisco Talos Blog
TaoSecurity Blog
TaoSecurity Blog
H
Heimdal Security Blog
G
GRAHAM CLULEY
Cloudbric
Cloudbric

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Pop any UI component into a floating Picture-in-Picture window.
Saurabh Shak · 2026-05-20 · via DEV Community

Project: pip-it-up

Why is Picture-in-Picture only for video? Bringing native PiP to React components with pip-it-up

We all love Video Picture-in-Picture. Whether it's watching a live stream on the side or catching up on a tutorial while you work, floating windows are incredibly useful. But it begs a simple question: why should video have all the fun?

Why can't we have native PiP for individual UI components?

As a developer who prefers the clean focus of a single-screen setup, I was tired of tab-switching. I wanted a way to tear away just a small, specific part of my web application a markdown editor, a task list, a diagnostic log viewer and stick it always-on-top of my IDE without losing context or breaking my flow.

This is the story of how I built pip-it-up: an open-source React toolkit for the browser's Document Picture-in-Picture API.


The Document PiP API: more powerful than you think

Most developers are familiar with the standard Video Picture-in-Picture API. It lets you pop a <video> element into a small floating window that stays on top of everything else on your screen. Useful, but limited it only works with video.

The Document Picture-in-Picture API is a different beast entirely. Instead of floating a video element, it opens a fully functional floating browser window that can contain any interactive HTML content. Buttons, inputs, iframes, canvas elements, React components all of it works inside a real, always-on-top floating window.

// The raw browser API
const pipWindow = await window.documentPictureInPicture.requestWindow({
  width: 400,
  height: 300,
});

// Move any DOM node into it
pipWindow.document.body.appendChild(myElement);

Enter fullscreen mode Exit fullscreen mode

On paper this is exactly what we need. In practice, using it directly in a React application is where things get painful.


The three engineering roadblocks

1. CSS stylesheet isolation

When you open a new PiP window, you get a completely blank document. Your Tailwind utility classes? Gone. Your Emotion or Styled Components rules? Gone. Your CSS Modules? Gone.

The PiP window has its own document object with its own <head>. None of the stylesheets from your main application are inherited, which means the moment you move a component into the PiP window, it renders as completely unstyled raw HTML.

This isn't a minor visual glitch, it completely breaks the component.

2. DOM moving vs. virtual DOM state

Here's where things get subtle. When you physically move a DOM node from one document into another (which is what the raw API requires), the browser treats it as a brand new element. For vanilla JavaScript this is manageable, but for React it's a disaster.

React's reconciler tracks component identity through the virtual DOM tree. When you physically reparent a DOM node into a new document, React loses track of it. The result: the component unmounts and remounts, which wipes all internal state, breaks event listeners, resets scroll positions, resets input cursor positions, and kills any active audio or animation state.

If you had a text input with a cursor halfway through a word, it's gone. If you had a Monaco editor open with unsaved changes, it's gone.

3. Browser support

The Document PiP API is currently supported in Chrome 116+ and Edge 116+. Firefox and Safari do not support it at all. Without a fallback strategy, your application simply breaks for a significant chunk of your users.


How pip-it-up solves all three

Real-time style syncing

Instead of hoping styles somehow transfer, pip-it-up uses a MutationObserver to watch your main document's <head> for any <style> or <link rel="stylesheet"> additions or changes, then dynamically clones and mirrors them into the PiP window's document in real time.

const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
      if (node.tagName === 'STYLE' || node.tagName === 'LINK') {
        pipWindow.document.head.appendChild(node.cloneNode(true));
      }
    }
  }
});

observer.observe(document.head, { childList: true, subtree: true });

Enter fullscreen mode Exit fullscreen mode

This means Tailwind utilities, CSS-in-JS injected styles, and CSS Modules all work perfectly inside the floating window. The sync is live, if a new stylesheet is injected after the PiP window opens, it gets mirrored automatically.

Virtual tree retention via React Portals

This is the core architectural insight of pip-it-up. Instead of destroying and recreating the React component in the new window, we use a React Portal to physically move the DOM node into the PiP window while keeping the virtual component instance exactly where it was in the tree.

The component never unmounts. React never loses track of it. All context, all state, all event handlers, all cursor positions remain perfectly intact. The component just happens to be rendering its DOM into a different document.

// Simplified version of how Portal Mode works
function PipPortal({ pipWindow, children }) {
  return pipWindow
    ? createPortal(children, pipWindow.document.body)
    : children;
}

Enter fullscreen mode Exit fullscreen mode

From React's perspective nothing changed. From the user's perspective, the component is now floating on top of their IDE.

Smart auto-sizing with ResizeObserver

The raw Document PiP API requires you to specify explicit width and height values when opening the window. This means you'd normally need to hardcode dimensions or manually pass them as props — a poor developer experience.

pip-it-up attaches a ResizeObserver to the component being floated and automatically measures its natural dimensions before opening the PiP window, then keeps the window dimensions in sync as the component resizes.

const resizeObserver = new ResizeObserver(([entry]) => {
  const { width, height } = entry.contentRect;
  // Sync PiP window dimensions automatically
  pipWindow.resizeTo(width, height);
});

resizeObserver.observe(componentRef.current);

Enter fullscreen mode Exit fullscreen mode

No width or height props required. It just works.

Graceful fallbacks for Firefox and Safari

When the Document PiP API isn't available, pip-it-up automatically detects this and falls back to a customizable popup, modal, or inline UI whatever you configure. Your users on Firefox and Safari never see a broken page; they just get a slightly different (but fully functional) experience.


Using it in your project

Installation is straightforward:

npm i @pip-it-up/react

Enter fullscreen mode Exit fullscreen mode

Basic usage with PipWrapper and PipTrigger

import { PipWrapper, PipTrigger } from '@pip-it-up/react';

function App() {
  return (
    <PipWrapper>
      <PipTrigger>
        <button>Float this widget</button>
      </PipTrigger>

      <div className="my-widget">
        <h2>Reference Checklist</h2>
        <ul>
          <li>Review PR comments</li>
          <li>Run test suite</li>
          <li>Update changelog</li>
        </ul>
      </div>
    </PipWrapper>
  );
}

Enter fullscreen mode Exit fullscreen mode

When the user clicks the trigger, the widget tears away into a native always-on-top floating window. Click it again and it snaps back with all its state perfectly preserved.

Floating a Monaco editor with state preservation

import { PipWrapper, PipTrigger } from '@pip-it-up/react';
import Editor from '@monaco-editor/react';

function CodePanel() {
  const [code, setCode] = useState('// Start coding...');

  return (
    <PipWrapper>
      <PipTrigger>
        <button>Pop out editor</button>
      </PipTrigger>

      <Editor
        height="400px"
        defaultLanguage="javascript"
        value={code}
        onChange={setCode}
      />
    </PipWrapper>
  );
}

Enter fullscreen mode Exit fullscreen mode

The editor floats into a native PiP window. Your cursor position, selection state, scroll position, and the code itself all survive the transition perfectly. You can type in the floating editor while your main application is focused in another window.


What you can build with this

A few ideas to get you thinking:

  • Floating reference panels: Keep a keyboard shortcut cheatsheet or API reference visible while you work in your IDE
  • Tear-away chat widgets: Pop a support chat or team messaging widget out of a SaaS tool and keep it on-screen
  • Floating code playgrounds: Let users experiment with code in a persistent floating window
  • Always-on-top dashboards: Pin a metrics panel or log viewer on top of your development environment
  • Persistent note-taking: Float a scratchpad widget that stays accessible regardless of what you're focused on

Try it

The live playground has interactive demos including a floating Monaco editor, a Tailwind layout widget, and a keyboard shortcut manager all showing real state preservation in action.

If you prefer a focused, single-screen workflow, I hope this helps you stay in the zone. And if you build something interesting with it, I'd genuinely love to hear about it in the comments.

What's the first component you'd float?