You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firefox/Chrome扩展开发:点击按钮注入随滚动悬浮内容

How to Build a Web Extension That Injects a Scroll-Synced Page Overlay (Like Bloomberg's NYT Integration)

Got it, let's break down how to build this overlay extension that works like Bloomberg's on NYT. I'll walk you through the exact steps, using modern Manifest V3 (supported by both Chrome and Firefox) and a <div>—way simpler than an iframe for this use case, since iframe adds unnecessary complexity for scroll sync and DOM integration.

Core Concepts to Nail Your Requirements

Your two key needs are:

  • Full page coverage: The overlay sits on top of all existing page content.
  • Scroll sync: The overlay moves in lockstep with the page's scroll position.

We'll cover two common implementations depending on what you mean by "scroll sync":

  1. Fixed Viewport Overlay: Stays anchored to the browser window (doesn't move when the page scrolls) — great for full-screen modals or persistent headers/sidebars.
  2. Document-Following Overlay: Extends the full height of the page and scrolls with it — perfect if you need to cover off-screen content as users scroll.

Step 1: Set Up the Extension Structure

First, create these files in a new folder:

your-extension/
├─ manifest.json
├─ popup.html
├─ popup.js
└─ content.js

Manifest.json (V3)

This file tells the browser about your extension's permissions and structure:

{
  "manifest_version": 3,
  "name": "Scroll-Synced Page Overlay",
  "version": "1.0",
  "action": {
    "default_popup": "popup.html"
  },
  "permissions": ["activeTab", "scripting"]
}
  • activeTab: Lets you interact with the currently open tab.
  • scripting: Lets you inject content scripts on demand when the user clicks your extension button.

Step 2: Build the Popup (Trigger for the Overlay)

The popup is a simple button that toggles the overlay on/off.

<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 220px; padding: 12px; margin: 0; font-family: Arial, sans-serif; }
    #toggleBtn { width: 100%; padding: 10px; border: none; border-radius: 4px; background: #0066cc; color: white; cursor: pointer; font-size: 14px; }
    #toggleBtn:hover { background: #0052a3; }
  </style>
</head>
<body>
  <button id="toggleBtn">Toggle Page Overlay</button>
  <script src="popup.js"></script>
</body>
</html>

Handles the button click, injects the content script (if not already present), and sends messages to control the overlay:

document.getElementById('toggleBtn').addEventListener('click', async () => {
  // Get the active tab
  const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
  
  // Check if our content script is already registered
  const registeredScripts = await chrome.scripting.getRegisteredContentScripts();
  const scriptExists = registeredScripts.some(script => script.id === 'overlayContent');

  if (scriptExists) {
    // Send a message to toggle the overlay
    await chrome.tabs.sendMessage(activeTab.id, { action: 'toggleOverlay' });
  } else {
    // Register and inject the content script
    await chrome.scripting.registerContentScripts([{
      id: 'overlayContent',
      matches: [`${activeTab.url}*`],
      js: ['content.js'],
      runAt: 'document_idle'
    }]);
    // Wait a split second for the script to load, then show the overlay
    setTimeout(async () => {
      await chrome.tabs.sendMessage(activeTab.id, { action: 'showOverlay' });
    }, 100);
  }
  
  // Close the popup after action
  window.close();
});

Step 3: Build the Content Script (Overlay Logic)

This is where we create the overlay and handle scroll sync. Choose one of the two implementations below.

Option 1: Fixed Viewport Overlay (Stays in Window)

Perfect for modals or persistent sidebars. If you want the overlay's internal content to sync with the page's scroll, add the scroll listener.

let overlay = null;

function createFixedOverlay() {
  overlay = document.createElement('div');
  overlay.id = 'ext-overlay';
  
  // Style: Full viewport coverage, fixed position, high z-index
  overlay.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.85);
    z-index: 999999;
    color: white;
    padding: 30px;
    box-sizing: border-box;
    overflow-y: auto; /* Enable scrolling inside the overlay if content is long */
  `;
  
  // Add your custom content
  overlay.innerHTML = `
    <h2>My Extension Overlay</h2>
    <p>This stays fixed in your browser window even as the page scrolls.</p>
    <p>Scroll down to see how the overlay's internal scroll syncs with the page!</p>
    <div class="spacer" style="height: 1500px;"></div>
  `;
  
  document.body.appendChild(overlay);
  
  // Optional: Sync overlay's internal scroll with the page
  window.addEventListener('scroll', syncOverlayScroll);
}

function syncOverlayScroll() {
  // Match the overlay's scroll position to the page's scroll position
  overlay.scrollTop = window.scrollY;
}

function toggleOverlay() {
  if (!overlay) {
    createFixedOverlay();
  } else {
    overlay.style.display = overlay.style.display === 'none' ? 'block' : 'none';
  }
}

// Listen for messages from the popup
chrome.runtime.onMessage.addListener((message) => {
  switch (message.action) {
    case 'showOverlay':
      if (!overlay) createFixedOverlay();
      else overlay.style.display = 'block';
      break;
    case 'toggleOverlay':
      toggleOverlay();
      break;
  }
});

Option 2: Document-Following Overlay (Scrolls with Page)

This overlay extends the full height of the page and moves with it, covering all content even as users scroll.

let overlay = null;

function createScrollingOverlay() {
  overlay = document.createElement('div');
  overlay.id = 'ext-overlay';
  
  // Style: Covers the entire document, scrolls with the page
  overlay.style.cssText = `
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    min-height: 100vh;
    background-color: rgba(0, 0, 0, 0.85);
    z-index: 999999;
    color: white;
    padding: 30px;
    box-sizing: border-box;
  `;
  
  // Add your custom content
  overlay.innerHTML = `
    <h2>My Scrolling Overlay</h2>
    <p>This moves with the page as you scroll, covering all content.</p>
  `;
  
  // Make sure the overlay matches the document's height if the page grows dynamically
  const updateOverlayHeight = () => {
    overlay.style.height = `${document.body.scrollHeight}px`;
  };
  updateOverlayHeight();
  window.addEventListener('resize', updateOverlayHeight);
  
  document.body.appendChild(overlay);
}

function toggleOverlay() {
  if (!overlay) {
    createScrollingOverlay();
  } else {
    overlay.style.display = overlay.style.display === 'none' ? 'block' : 'none';
  }
}

// Listen for messages from the popup
chrome.runtime.onMessage.addListener((message) => {
  switch (message.action) {
    case 'showOverlay':
      if (!overlay) createScrollingOverlay();
      else overlay.style.display = 'block';
      break;
    case 'toggleOverlay':
      toggleOverlay();
      break;
  }
});

Key Tips for Success

  • Z-Index Priority: Set z-index: 999999 to ensure your overlay sits above all page content. Some sites use high z-indexes, so you might need to bump this up if needed.
  • Style Isolation: To prevent the page's CSS from breaking your overlay, add all: unset to the overlay's style (then re-add your desired styles) or use a scoped CSS class.
  • Dynamic Content: If the page loads content dynamically (like infinite scroll), update the overlay's height (as shown in Option 2) to keep covering new content.
  • Testing: Test on sites like NYT to ensure compatibility—most news sites don't block extension DOM injections, but some might have strict CSP rules (you can adjust the manifest if needed).

内容的提问来源于stack exchange,提问作者Foobar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:23:38