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

Chrome扩展如何在当前页面嵌入固定侧边栏展示输出内容

Chrome扩展左侧固定文本展示侧栏实现方案

组件标准称谓

这类注入到第三方网页、固定在视口位置、不随页面滚动、与原页面内容区共存的内嵌侧边栏组件,在浏览器扩展开发领域的标准通用称谓是内容脚本注入式固定侧栏(Content Script Injected Fixed Sidebar),核心特征是独立于原页面布局流、样式逻辑双隔离,是扩展类工具实现页面内嵌功能面板的主流方案。

原有方案的问题

直接修改body的position属性的方案兼容性极差:该操作会破坏整个页面的定位上下文,对使用了sticky导航、fixed悬浮按钮、绝对定位弹窗的站点会直接造成布局错位,且没有做样式隔离,很容易被站点原有CSS规则干扰,也容易被站点高z-index元素覆盖。

通用兼容实现思路

要实现全站点兼容,核心要做到4点:

  • 用Shadow DOM做侧栏的完全样式隔离,侧栏所有样式、DOM结构都放在Shadow Root内部,既不会被站点原有CSS污染,也不会泄露样式影响原页面
  • 不要修改body/html的position属性,仅给html标签添加和侧栏等宽的左padding,把原页面所有内容整体向右偏移,完全不遮挡原内容,也不会破坏原页面内部所有元素的定位上下文
  • 侧栏本身使用position: fixed定位固定在视口左侧,设置CSS支持的最大z-index值2147483647,避免被站点的fixed/sticky元素覆盖
  • 侧栏插入到document.documentElement(即html标签)下,避免被页面内其他overflow容器裁剪

完整实现代码

content.js

const SIDEBAR_CONFIG = {
  width: '400px',
  maxZIndex: 2147483647
}
let collectedTexts = []
let sidebar = null

function initSidebar() {
  if (sidebar) return

  // 创建侧栏宿主节点
  const sidebarHost = document.createElement('div')
  sidebarHost.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: ${SIDEBAR_CONFIG.width};
    height: 100vh;
    z-index: ${SIDEBAR_CONFIG.maxZIndex};
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
  `

  // 开启Shadow DOM实现完全样式隔离
  const shadow = sidebarHost.attachShadow({ mode: 'open' })
  shadow.innerHTML = `
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }
      .panel {
        width: 100%;
        height: 100%;
        background: #fff;
        border-right: 1px solid #e5e7eb;
        padding: 16px;
        overflow-y: auto;
        font-family: system-ui, sans-serif;
        font-size: 14px;
        line-height: 1.6;
        color: #111;
      }
      .panel-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding-bottom: 12px;
        margin-bottom: 12px;
        border-bottom: 1px solid #e5e7eb;
        font-weight: 600;
        font-size: 16px;
      }
      .close-btn {
        border: none;
        background: #f3f4f6;
        padding: 4px 10px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 12px;
      }
      .content {
        white-space: pre-wrap;
        word-break: break-all;
      }
    </style>
    <div class="panel">
      <div class="panel-header">
        <span>收集的文本</span>
        <button class="close-btn">关闭</button>
      </div>
      <div class="content"></div>
    </div>
  `

  // 关闭逻辑
  shadow.querySelector('.close-btn').addEventListener('click', () => {
    sidebarHost.remove()
    document.documentElement.style.paddingLeft = '0'
    sidebar = null
  })

  // 插入侧栏,偏移原页面内容
  document.documentElement.appendChild(sidebarHost)
  document.documentElement.style.paddingLeft = SIDEBAR_CONFIG.width
  document.documentElement.style.overflowX = 'hidden'

  sidebar = {
    host: sidebarHost,
    content: shadow.querySelector('.content')
  }
}

function getSelectionText() {
  let text = ''
  if (window.getSelection) {
    text = window.getSelection().toString()
  } else if (document.selection && document.selection.type !== 'Control') {
    text = document.selection.createRange().text
  }
  return text
}

function onKeyUp(e) {
  const selected = getSelectionText()
  if (selected && e.key === '1') {
    initSidebar()
    collectedTexts.push(selected)
    sidebar.content.textContent = collectedTexts.join('\n\n---\n\n')
    sidebar.content.scrollTop = sidebar.content.scrollHeight
  }
}

console.log('Text collect extension running')
document.addEventListener('keyup', onKeyUp, false)

manifest.json

原有配置仅需调整content_scripts的注入时机,保证尽早注入即可:

{
  "name": "选中文本收集侧栏",
  "description": "按数字键1收集选中文本,展示在左侧固定侧栏",
  "version": "1.0",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ],
  "permissions": ["tabs"]
}

兼容性说明

  • 样式完全隔离:Shadow DOM内部样式不受站点CSS影响,也不会干扰原页面样式,从根源解决样式冲突问题
  • 无布局侵入:仅修改html标签的左padding,不改动任何元素的position属性,原页面内的absolute/fixed/sticky元素定位逻辑完全不受影响,不会出现布局错乱
  • 防覆盖:使用CSS支持的最大z-index值,侧栏始终位于视口最上层,不会被站点导航、弹窗等元素遮挡
  • 位置固定:侧栏采用fixed定位,原页面滚动时位置始终保持在视口左侧,不会随页面偏移

内容的提问来源于stack exchange,提问作者Consider Non-Trivial Cases

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:36:47