你以为 PWA 窗口拖拽只能靠非标准属性?Chrome 今天把这件事彻底原生化了

做过 Electron 桌面应用、PWA 安装后的自定义 titlebar,或者任何需要隐藏浏览器原生窗口边框的场景,你一定碰到过这个问题:拖拽区域怎么写?

很长一段时间,答案都是 app-region: drag——一个 WebKit/Blink 私有的非标准属性。你去 MDN 查,搜到的文档写的都是实验性警告。你去 caniuse 查,Safari 一栏永远是 No signal。

这不是开发者不知道标准不等同于好用的区别——大家只是没有选择。

Chrome 152 把这件事彻底原生化了。

Chrome 152(2026-08-25 稳定版)正式支持了 window-drag: move,这是 W3C CSS UI Level 4 规范里的标准属性。它的作用和 app-region: drag 完全一样:让一个元素的点击拖拽行为变成移动整个窗口——但这是正经的 CSS 属性,不是私有前缀的 Hack。

具体用法:

/* 把整个 header 变成窗口拖拽区 */
.header {
  window-drag: move;
}

/* 按钮不参与拖拽,必须显式排除 */
.header button {
  window-drag: none;
}

就这么两行。以前你要写 -webkit-app-region: drag-webkit-app-region: no-drag,现在有了一个所有浏览器最终都会认的标准写法。

一个属性,背后是两份历史债务

app-region 最早是 Chrome 为了支持 Electron 应用和 Chrome App 的自定义窗口标题栏加的。Electron 把它发扬光大,所有做桌面端 PWA 的团队都在用。但它从来没进过任何标准——它是 WebKit 的实验性功能,后来靠 Chromium 强推才成了事实标准。

CSS Working Group 最终决定把这个能力收编进 CSS UI Level 4,改名 window-drag,值从 drag/nodrag 改成 move/none——更直观,也更符合 CSS 属性的命名惯例。

迁移成本:零

这是这次更新最良心的地方。Chrome 152 没有废弃 app-region,也没有要求你立刻迁移。内部实现上,app-region 就是一个映射到 window-drag 的别名,两套写法在 Chromium 里完全等价。你现在去改也行,不改也行,浏览器不会报警告。

但建议尽快用标准属性更新代码,因为 Firefox 已经对 window-drag 投了 Positive,Safari 还没表态——等 Safari 也支持了,纯标准的写法才能真正通用。

和 Window Controls Overlay 配合使用

window-drag 最典型的使用场景是配合 Window Controls Overlay(WCO)做自定义 titlebar。WCO 让你把窗口控制按钮(关闭/最小化/最大化)覆盖在页面内容上,window-drag 让你把页面的任意区域变成拖拽句柄。两个 API 组合,就是一个完整的自定义窗口:

.titlebar {
  /* 窗口控制按钮区域 */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 40px;
  window-drag: move;          /* 整条 titlebar 可拖动窗口 */
  -webkit-app-region: drag;   /* Safari fallback,仍需前缀版 */
}

.titlebar button {
  window-drag: none;          /* 按钮不参与拖拽,可点击 */
  -webkit-app-region: no-drag;
}

注意 -webkit-app-region 仍然需要保留作为 Safari 的 fallback——目前 Safari 还没实现 window-drag,但这个状态迟早会变。

下一步怎么做

如果你正在做 Electron 应用、PWA 安装桌面版,或者任何需要自定义窗口标题栏的场景,现在去把你的 -webkit-app-region: drag 改成 window-drag: move,把 -webkit-app-region: no-drag 改成 window-drag: none。保留旧写法作为 Safari fallback,直到 Safari 跟进支持。Chrome 已经稳定大半年,这个迁移窗口期已经成熟了。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 13 阅读