无边框窗口必须设 frame: false,但仅此不够:它会移除原生标题栏、禁用拖拽/最大化等交互,需手动添加 -webkit-app-region: drag、setMenu(null) 及 IPC 控制窗口行为。

无边框窗口必须设 frame: false,但仅此不够
Electron 中启用无边框窗口最基础的一步是创建 BrowserWindow 时传入 { frame: false }。但这只是起点——它会直接移除系统标题栏和边框,同时也会禁用窗口拖拽、双击最大化、右键缩放等所有原生行为。如果你还希望保留这些交互(比如拖动窗口、双击放大),就必须手动接管。
常见错误是只设 frame: false 就开始写 CSS,结果发现标题栏区域点不动、窗口无法拖拽、最大化按钮点了没反应。这是因为 Electron 默认把整个渲染进程视图当作“内容区”,不识别你写的 HTML 元素是否该承担标题栏职责。
关键补救动作有三步:
- 在主进程里调用
mainWindow.setMenu(null),避免右上角菜单干扰 - 在渲染进程的标题栏元素上加 CSS:
-webkit-app-region: drag - 在标题栏内部的按钮(如最小化、关闭)上加:
-webkit-app-region: no-drag
SCSS 变量需适配多平台窗口控制区高度
Windows、macOS、Linux 的原生标题栏高度不同(macOS 约 22px,Windows 默认 30px+,Linux 更多变)。如果你用 SCSS 写死 $titlebar-height: 32px,在 macOS 上就会显得头重脚轻,或导致拖拽热区偏移。
更稳妥的做法是定义平台感知变量,再配合 @supports 或 JS 注入类名做微调:
- 在
variables.scss中按需声明:$titlebar-height-macos: 24px、$titlebar-height-win: 36px - 在根元素上由主进程注入平台类:
(通过process.platform判断) - SCSS 中用嵌套写法:
.platform-win .titlebar { height: $titlebar-height-win; }
不要依赖 env() 或 safe-area-inset,它们在无边框窗口中不可靠,且 Electron 渲染进程不支持部分 CSS 环境变量。
transparent: true + backgroundColor: '#00000000' 才真正透明
只设 transparent: true 不足以让窗口背景变透明——它只是开启透明通道,实际颜色仍由 backgroundColor 控制。如果漏掉后者,窗口会显示为纯黑或纯白(取决于系统默认),尤其在深色模式下极易翻车。
SCSS 本身不参与窗口级透明控制,但你可以用它统一管理「视觉透明」与「逻辑透明」的边界:
- 确保主窗口配置含这两项:
transparent: true和backgroundColor: '#00000000' - 在 SCSS 中避免对
.titlebar使用background: rgba(..., 0.9)类似值,这会让拖拽区半透明但底层窗口不透,造成视觉割裂 - 若需模糊效果(如 macOS 的 vibrancy),需额外调用
mainWindow.setVibrancy('sidebar'),SCSS 无法模拟
右键缩放、双击最大化得靠 JS 监听,CSS 做不了
有人试图用 SCSS 的 :hover 或 ::after 伪元素模拟双击放大按钮状态,这是无效的。窗口级行为(如最大化、缩放、全屏)必须由主进程控制,渲染进程只能触发 IPC 通信。
典型实现链路是:
- 渲染进程监听标题栏
dblclick事件 → 发送ipcRenderer.send('window:toggle-maximize') - 主进程监听
ipcMain.on('window:toggle-maximize')→ 调用mainWindow.isMaximized() ? mainWindow.unmaximize() : mainWindow.maximize() - 右键菜单同理,但注意:Electron 默认禁用渲染进程右键菜单,需显式调用
mainWindow.webContents.on('context-menu', ...)
容易被忽略的是:双击事件在高 DPI 屏幕或缩放比例非 100% 时可能失灵,建议改用 click + 时间间隔判断(如两次 click 间隔 dblclick 更稳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











