Electron 无边框与透明窗口样式指南:从 frame:false 到真正的异形窗口
本文是 custom-window-styles.md 的深度展开,系统讲解在 Electron 中打造"无系统装饰"与"真正透明"两类自定义窗口的核心原理与完整可运行示例。读完你将掌握 frame、transparent、hasShadow、roundedCorners 等关键构造参数的真实语义、平台差异与各项硬性限制,并能在自己的 BrowserWindow / BaseWindow 应用中直接复用文中的示例工程。
窗口样式定制的入口:BrowserWindow 与 BaseWindow
在进入具体实现之前,需要先理解 Electron 窗口模型的整体背景。Electron 的 BrowserWindow 模块是应用窗口的基础,它派生自 BaseWindow 模块,二者都可以创建和管理窗口,主要区别在于:BrowserWindow 内置一个占满窗口的完整 Web 视图,而 BaseWindow 支持组合多个 View。在本文的示例中,二者可以互换使用,相关说明见 window-customization.md 与 browser-window.md。
本文涉及的构造参数(frame、transparent、hasShadow 等)都属于 BaseWindowConstructorOptions,其完整定义位于 base-window-options.md。下面每一个参数默认值、平台行为均以该文档与仓库中的可运行 fiddle 为准。
仓库中针对本主题提供了一组开箱即用的完整示例,位于 docs/fiddles/features/window-customization/custom-window-styles/,下文的无边框与透明窗口代码即来自其中,可直接作为最小复现工程使用。
无边框窗口(Frameless Windows)
什么是无边框窗口
无边框窗口会移除操作系统附加的全部 chrome(chrome 指代浏览器/桌面环境提供的窗口边框、标题栏、关闭/最小化/最大化按钮等 UI 装饰,即 Glossary 意义上的"界面壳层"),让应用内容以更纯净的形态呈现。这在需要完全自定义 UI、沉浸式展示或自绘标题栏时非常常见。
如何创建:frame: false
创建无边框窗口的方法很简单:在 BrowserWindow(或 BaseWindow)构造函数中将 frame 参数设为 false。该参数在 base-window-options.md 中的定义为:frame(boolean,可选)——设为 false 以创建无边框窗口,默认值为 true。
仓库中对应的最小示例位于 frameless-windows/main.js,完整内容如下:
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 300,
height: 200,
frame: false
})
win.loadURL('https://example.com')
}
app.whenReady().then(() => {
createWindow()
})
这个示例创建了一个 300×200、无任何窗口装饰的窗口并加载网页内容,是整个 Electron 中最简短的无边框窗口"hello world"。
无边框不等于"零装饰":相关参数组合
仅设置 frame: false 只是去掉了系统标题栏与按钮,窗口仍可能带有阴影、圆角等外观,并可通过系统默认行为进行缩放。根据 base-window-options.md 中相关构造参数的定义,实际项目通常还需要配合以下选项精确控制无边框窗口的外观:
hasShadow(boolean,默认true):决定窗口是否带阴影。若不希望系统绘制阴影,可设为false。roundedCorners(boolean,默认true):决定无边框窗口是否带圆角。在 Windows 11 Build 22000 之前的版本上此参数无效(无边框窗口不会有圆角);在 Linux 上仅当桌面环境支持客户端侧装饰(client-side decorations)时才会绘制圆角。titleBarStyle:在无边框窗口的基础上,还可以用hidden、hiddenInset(macOS)、customButtonsOnHover(macOS)等取值控制标题栏与 macOS "红绿灯"按钮的呈现方式,构建"标题栏隐藏但保留系统按钮"的效果。titleBarOverlay:与无边框窗口搭配,可启用 Window Controls Overlay 相关的 JavaScript API 与 CSS 环境变量,用于实现自定义标题栏。trafficLightPosition(macOS):为无边框窗口自定义"红绿灯"按钮的位置。thickFrame(Windows,默认true):为 Windows 上的无边框窗口启用WS_THICKFRAME样式(即保留标准窗口框)。若设为false,会移除窗口阴影和窗口动画,并禁用通过拖拽窗口边缘来调整大小的能力。
由于 frame: false 后不再有系统拖拽区域,让内容区可被鼠标拖动通常是刚需。仓库中的 custom-window-interactions.md 以及 custom-window-styles 下的透明窗口示例 都展示了通过 CSS 的 app-region: drag 区域声明来拖动窗口的做法,实现细节可参考 custom-window-styles.md 同目录的 custom-title-bar.md 主题。
Wayland(Linux)下的特殊行为
文档特别指出:在 Linux 的 Wayland 协议下,无边框窗口默认会带有 GTK 投影阴影与扩展的缩放边界(extended resize boundaries)。若希望得到一个"完全不绘制任何装饰"的彻底无边框窗口,需要在构造参数中额外显式设置 hasShadow: false(hasShadow 默认值虽为 true,但 Wayland 下无边框窗口的阴影来自 GTK 装饰层,必须显式关闭)。
透明窗口(Transparent Windows)
如何创建:transparent: true
要创建完全透明的窗口,需要在构造函数中把 transparent 参数设为 true。该参数在 base-window-options.md 中的定义要点包括:
- 默认值为
false; - 在 Windows 上,除非窗口同时是无边框的,否则透明不生效;
- 当向
BaseWindow添加View时,还需要在该View上调用view.setBackgroundColor并传入透明背景色,才能使该View的背景同样透明。
文档中配套的 fiddle(transparent-windows)利用"透明窗口 + CSS 样式"制造出一个圆形窗口的视觉假象,即:窗口本身透明,页面内容中只绘制一个白色圆形区域。工程文件位于 transparent-windows/ 目录下,主进程代码 main.js 如下:
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 100,
height: 100,
resizable: false,
frame: false,
transparent: true
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
注意此处与无边框示例的差异:窗口同时设置了 frame: false 与 transparent: true,且显式把 resizable 设为 false。结合下面文档列出的限制可以看出,"不可缩放"是透明窗口的稳定前提(见后文 Limitations 部分)。
页面文件 index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
<link href="./styles.css" rel="stylesheet">
<title>Transparent Hello World</title>
</head>
<body>
<div class="white-circle">
<div>Hello World!</div>
</div>
</body>
</html>
样式文件 styles.css 是整个"圆形窗口"效果的关键:
body {
margin: 0;
padding: 0;
background-color: rgba(0, 0, 0, 0); /* Transparent background */
}
.white-circle {
width: 100px;
height: 100px;
background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
app-region: drag;
user-select: none;
}
实现要点拆解:
body背景被设为rgba(0, 0, 0, 0)(完全透明),这是让窗口视觉透明的关键——窗口的透明基于渲染出的网页背景,HTML 背景不透明时窗口也就不透明;- 真正可见的内容是
.white-circle这个 100×100 的白色圆形div,配合border-radius: 50%呈现圆形外观; app-region: drag声明使该圆形区域可以被当作标题栏一样拖动窗口(弥补无边框窗口没有系统拖拽区域的不足);user-select: none防止拖拽过程中误选中文本。
由于窗口尺寸(100×100)与圆形 div 尺寸一致,最终用户看到的就是一个"圆形窗口",这正是"透明窗口 + CSS"打造异形窗口的通用套路。
透明窗口的限制(Limitations)
透明窗口并不等同于"完全自由"的窗口,文档明确列出了若干使用中必须接受的边界条件,这些限制直接影响技术选型:
- 无法穿透透明区域点击:不能点击穿过透明区域到达下面的内容。即透明只是"视觉上的透明",命中测试仍按整块窗口区域进行(Windows 上透明区域的点击穿透需要另行使用其它 API 方案,详见 browser-window.md 相关说明与官方 issue 讨论)。
- 透明窗口不可缩放:将
resizable设为true可能使某些平台上的透明窗口停止正常工作。因此示例中显式设置resizable: false。 - CSS
blur()滤镜只作用于窗口自身内容:它只能模糊窗口内(Web contents)的元素,无法对窗口下方其他应用的内容产生模糊。也就是说,无法用这种方式实现 iOS 风格的"背景毛玻璃"遮罩效果。 - 打开 DevTools 时窗口将不再透明:调试主内容时会临时失去透明效果。
- Windows 平台:
- 透明窗口不能通过 Windows 系统菜单或双击标题栏的方式最大化(相关背景见上游 PR 讨论,原因与 Windows 的最大化路径相关)。
- macOS 平台:
- 透明窗口不会显示原生窗口阴影。
更进一步的窗口定制思路
掌握了 frame 与 transparent 两个开关之后,围绕"自定义窗口样式"还可以继续扩展的方向包括:
- 自定义标题栏而非完全无边框:如果你仍希望保留系统窗口按钮(如 macOS 的"红绿灯"),
titleBarStyle: 'hidden'是不错的选择,它隐藏标题栏但保留系统按钮。相关 fiddle 见 custom-title-bar/,文档见 custom-title-bar.md。 - 圆角与背景色控制:通过
roundedCorners、backgroundColor、hasShadow等参数(定义见 base-window-options.md)精细调节窗口外观;backgroundColor在transparent: true时还可配合#AARRGGBB形式的 Alpha 值使用。 - 平台特性叠加:macOS 的
vibrancy、Windows 的backgroundMaterial(如 Mica/Acrylic)等参数能进一步定制系统级材质外观,但这些与"完全透明"目标并存时需要按平台单独验证。 - 窗口尺寸与拖拽行为:无边框、透明窗口常与自绘拖拽区(
app-region: drag)、无边框自定义交互相结合,仓库的 custom-window-interactions.md 对该主题有系统讲解。
小结
本文以仓库中的 custom-window-styles.md 为主线,还原并扩充了 Electron 无边框窗口与透明窗口的完整实现:核心只有两个开关——frame: false 移除系统 chrome,transparent: true 打开窗口透明通道;而真正的"异形窗口"外观则由 HTML/CSS 在透明画布上绘制。同时必须牢记平台的硬性边界:Wayland 下需额外关闭阴影、Windows 下透明必须配合无边框、透明窗口不可缩放且无法穿透点击、DevTools 会破坏透明效果等。配合 base-window-options.md 中的构造参数定义,你完全可以在自己的 Electron 应用中快速复现出纯净的无边框 UI 或真正的异形透明窗口。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


