首页 / Wails 入门教程 / 无边框窗口 Frameless

Wails 入门教程

无边框窗口 Frameless

本教程共 42 篇 · 第 21 篇 · 更新于 2026-08-03

Wails桌面开发无边框Frameless拖拽区

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 章的 WindowMinimiseWindowHide 之类的方法。

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 不方便。

这时候可以换一个你自己的属性名。靠 CSSDragPropertyCSSDragValue 改:

Frameless:       true,
CSSDragProperty: "widows",
CSSDragValue:    "1",

前端就写成:

<body style="widows: 1">

Wails 会按你给的属性名和值去找拖拽区。

Note

默认值其实就是 --wails-draggabledrag。只有默认不够用时才去改这两个字段,大多数项目用默认就行。

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 子项里调 DisableFramelessWindowDecorationsBackdropType,那是平台专属配置,后面打包章节会展开。

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 比到处打补丁省事得多。