配了三年桌面 PWA,每次自定义窗口拖拽都要靠 -webkit-app-region 黑魔法——今天 window-drag 把这件事彻底标准化了

你做桌面 PWA 或者套 Electron 壳的时候,有没有想过把浏览器原生的标题栏藏掉,自己画一套?这时候问题来了——怎么让某个区域能拖动窗口?

过去解法是 -webkit-app-region: drag。这个属性 Chromium 先用,后来 Electron 跟进,几乎成了业界事实标准。但它从来没进过 CSS 规范,是个纯正的「浏览器私有属性」。

Chrome 152 把这件事扳过来了。

window-drag 是什么

CSS Basic User Interface Module Level 4 规范里新增了 window-drag 属性,用来声明页面上的某个区域「拖动这个区域 = 拖动整个应用窗口」。值有两个:

/* 声明为可拖拽窗口区域 */
.titlebar {
  window-drag: move;
}

/* 取消拖拽,让子元素恢复可交互 */
button {
  window-drag: none;
}

对应的就是旧的 -webkit-app-region: drag-webkit-app-region: no-drag。只不过现在名字改成了标准化版本,语义更准确(move vs none,比 drag vs no-drag 更好理解),且自带 CSS 继承行为——子元素默认继承 none,不需要每个按钮单独写一遍。

实际怎么用

最典型的场景是 PWA 自定义标题栏:

<script>
  if (windowControlsOverlay in navigator) {
    // 根据窗口控件位置动态适配背景
    const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
    document.body.classList.toggle(controls-right, x > 0);
  }
</script>
<header class="titlebar">
  <span class="app-title">My App</span>
  <div class="window-controls">
    <button id="minimize">─</button>
    <button id="maximize">☐</button>
    <button id="close">✕</button>
  </div>
</header>
.titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 把整个 header 声明为窗口拖拽区 */
  window-drag: move;
  /* 防止拖拽时选中文本 */
  user-select: none;
  /* 保证标题栏在内容上方 */
  z-index: 9999;
  /* 适配窗口控件位置(Linux/Windows 在右,macOS 在左) */
  background: linear-gradient(90deg,
    #36c, 45%,
    var(--bg) 90%);
}
.titlebar.controls-right {
  background: linear-gradient(90deg,
    #36c, var(--bg) 33%, var(--bg));
}

/* 窗口控制按钮取消拖拽,恢复可点击 */
.window-controls button {
  window-drag: none;
  background: transparent;
  border: none;
  cursor: pointer;
}

这就是 PWA 里 Window Controls Overlay 的标准配合用法。navigator.windowControlsOverlay.getTitlebarAreaRect() 能拿到原生标题栏占用的矩形区域,帮你动态计算自定义标题栏的背景渐变方向,保证视觉上「原生标题栏」和「自定义标题栏」无缝衔接。

和旧属性怎么迁移

已有的项目不用担心,Chromium 内部把 app-region 实现成了 window-drag 的别名,两套写法同时生效:

/* 旧写法,Chromium 内部映射到 window-drag,完全兼容 */
.titlebar {
  -webkit-app-region: drag;
}
button {
  -webkit-app-region: no-drag;
}

新增代码建议直接用 window-drag。CSS 工作组这次没有废弃旧属性,只是加了一层标准化别名,过渡是平滑的。

浏览器支持情况

浏览器 支持
Chrome 152+
Edge 152+
Firefox Positive(有意实现)
Safari 暂无信号

目前只有 Chromium 系浏览器(Chrome/Edge)稳定支持,但 Firefox 那边已经是 Positive 信号,进了标准化快车道。Electron 应用里因为本身就是 Chromium 内核,-webkit-app-region 早就生效,升级到 window-drag 只需要改一行属性名。

什么时候用它

window-drag 解决的是「桌面 Web 应用」这个场景里的原生体验问题:

用它的场景:

  • PWA 安装到桌面后,想隐藏原生标题栏、自己画标题栏
  • Electron/Tauri 套壳应用,需要自定义窗口控制按钮(最小化/最大化/关闭)
  • 任何想把某个区域变成「窗口拖拽手柄」的 Web 页面

不需要它的场景:

  • 普通移动端/桌面浏览器里的网页——用户本来就不应该能拖动页面里的某个 div 去移动浏览器窗口
  • macOS/Linux 上用原生标题栏的桌面应用

app-region 之所以成为事实标准,就是因为桌面 Web 应用场景真实存在。现在它进了 CSS 规范,意味着未来跨浏览器一致性和工具链支持都会更好。如果你现在正在做 PWA 桌面化或者 Electron 应用,window-drag: move 值得现在就换上去——一行属性的事。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 45 阅读