无边框窗口 Frameless
本教程共 42 篇 · 第 21 篇 · 更新于 2026-08-03
21. 无边框窗口 Frameless
本节目标
- 能用 Frameless 去掉系统默认的标题栏和边框。
- 用 CSS 变量圈出”可拖拽区域”,做出自己的标题栏。
- 知道全屏会禁用拖拽,以及怎么关掉弹性滚动。
21-1 开启无边框
普通窗口头顶有条标题栏,四周还有边框。
想做那种一整块都是界面的现代风格,把它去掉就行。
在 options.App 里设 Frameless: true:
func main() {
err := wails.Run(&options.App{
Title: "码上学笔记",
Width: 1024,
Height: 768,
Frameless: true,
AssetServer: &assetserver.Options{
Assets: assets,
},
Bind: []interface{}{app},
})
if err != nil {
log.Fatal(err)
}
}
去掉边框后,右上角的最小化、关闭按钮也没了。这些得你自己用前端按钮做,再调用第 19 章的 WindowMinimise、WindowHide 之类的方法。
Note无边框不等于全屏。它只是拿掉了系统装饰,窗口尺寸还是你设的 Width 和 Height,位置也能自由拖动。
21-2 用 CSS 指定拖拽区
边框没了,窗口怎么拖?总不能让用户拖不动吧。
Wails 的方案很巧:哪个 HTML 元素带 --wails-draggable: drag 这个样式,哪里就能当”抓手”。
<body style="--wails-draggable: drag">
<div id="logo"></div>
<div id="input" style="--wails-draggable: no-drag">
<input id="name" type="text" />
<button onclick="greet()">打招呼</button>
</div>
<div id="result"></div>
</body>
上面这段里,整个 body 都能拖。但输入框那个 div 写了 no-drag,所以用户在输入框里按鼠标不会误拖窗口。
Tip这个属性会”遗传”给所有子元素。你给 body 加了 drag,里面的按钮、文字默认都能拖。只有明确写
no-drag的地方才不动。
做自定义标题栏时,通常把顶部一条设为 drag,下面的内容区保持 no-drag。这样既能拖,又不影响操作。
21-3 自定义拖拽属性
有些框架动态生成样式,写死 --wails-draggable 不方便。
这时候可以换一个你自己的属性名。靠 CSSDragProperty 和 CSSDragValue 改:
Frameless: true,
CSSDragProperty: "widows",
CSSDragValue: "1",
前端就写成:
<body style="widows: 1">
Wails 会按你给的属性名和值去找拖拽区。
Note默认值其实就是
--wails-draggable配drag。只有默认不够用时才去改这两个字段,大多数项目用默认就行。
21-4 全屏与弹性滚动
无边框窗口要是允许全屏,拖拽会失效。
原因很简单:全屏时窗口铺满屏幕,没有”拖动”的概念了。所以你一旦切到全屏,之前设的 drag 区域就不起作用,回到普通窗口又恢复。
Warning如果你做了自定义标题栏靠 drag 拖动,记得全屏状态下给用户别的方式操作,比如保留几个可见按钮。否则全屏后用户可能”抓不住”窗口。
另一种常见毛病是弹性滚动。手机或触屏上,滚到页面尽头还往下拽,会出现回弹白边。
无边框界面里这圈白边特别扎眼。用一段 CSS 关掉它:
html {
height: 100%;
overflow: hidden;
}
overflow: hidden 把超出内容藏起来,回弹效果就没了。
Tip这条 CSS 对所有 Wails 应用都建议加。哪怕不是无边框,也能让界面更干净,不会出现诡异的橡皮筋边。
21-5 实战:自定义标题栏
做个自定义标题栏。顶部一条是 drag 区,里面放标题和两个按钮(最小化、关闭)。下面的内容区是 no-drag。
<div id="titlebar" style="--wails-draggable: drag; display:flex; justify-content:space-between">
<span>码上学笔记</span>
<span>
<button onclick="min()">-</button>
<button onclick="close()">×</button>
</span>
</div>
<div id="content" style="--wails-draggable: no-drag">
<!-- 正文 -->
</div>
按钮在 drag 区域内,但按钮本身要接收点击。这里有个细节:按钮如果也在 drag 区里,按住按钮拖动会连窗口一起拖。给按钮单独加 --wails-draggable: no-drag,点击和拖动就分开了。
Tip双击标题栏最大化,是桌面应用的习惯。在标题栏元素上监听
dblclick,调WindowToggleMaximise即可,体验立刻专业起来。
21-6 调试小贴士
调试无边框时两个常见现象。
一是窗口拖不动。先确认 Frameless 开了,再确认你圈了 --wails-draggable: drag 的区域,且那个区域没被 no-drag 覆盖。
二是拖动时偶发触发了文字选中。给 drag 区域加 user-select: none,避免拖拽顺手选中了标题文字。
Note无边框窗口在 Windows 上默认没有圆角和阴影。想要那种精致感,去 options 的 Windows 子项里调
DisableFramelessWindowDecorations和BackdropType,那是平台专属配置,后面打包章节会展开。
21-7 边缘缩放与拖拽共存
无边框窗口拿掉了边框,那用户怎么拉大拉小窗口?
好消息是 Wails 会自动处理。框架在窗口边缘保留了几像素的”隐形手柄”,鼠标移到边上光标会变成缩放箭头,拖动就能改尺寸。你不用自己写任何代码。
不过这种自动手柄只在普通无边框下有效。如果你做了完全自定义、连边缘都要自己画的界面,缩放就得自己接管,那复杂度就上去了。
如果你发现窗口既拖不动也拉不大,按这个清单排查:第一,Frameless 有没有开;第二,drag 区域有没有被 no-drag 误覆盖;第三,是不是同时设了 DisableResize 把缩放锁死了。
Tip想完全禁用手动缩放又保留无边框外观,把
DisableResize设为 true 即可。这时边缘手柄不会被激活,窗口大小完全由代码控制。
Warning在 macOS 上,无边框再叠加
DisableFramelessWindowDecorations可能导致窗口没有圆角和阴影,看起来像块生硬的矩形。要质感就别关这个装饰。
21-8 排错清单
无边框窗口的调试要点。
第一,窗口整体拖不动。按顺序查:Frameless 开了吗、drag 区域写了 --wails-draggable: drag 吗、那个区域有没有被 no-drag 覆盖、CSS 变量名和 options 里的 CSSDragProperty 对得上吗。
第二,拖动时选中了文字。给 drag 区域加 user-select: none。
第三,全屏后拖不动。这是预期行为,全屏没有拖动概念,回到普通窗口就恢复。
第四,边缘拉不动。确认没设 DisableResize,且不是完全自绘界面接管了缩放。
Tip用浏览器开发者工具检查元素的计算样式,确认
--wails-draggable的值确实是drag。有时被别的 CSS 规则覆盖,肉眼看不出来,开发者工具一目了然。
常见误区
Warning全屏会直接禁用 drag 拖拽。别指望在无边框全屏窗口里还能拖标题栏,那是矛盾的。
Note
no-drag要写在”不想拖”的具体元素上,而不是父级。它只覆盖当前元素,不影响兄弟节点。
Tip弹性滚动的根因是
html高度没锁死。加一句height:100%; overflow:hidden比到处打补丁省事得多。