狸花云移动端打磨记:抽屉、头像菜单与一个 height:100vh 引发的连环坑

一、今天改了什么

一天之内从 v5.6.0 推到 v5.7.2,主题只有一个:移动端真正可用了。

版本 改动
v5.6.0 侧栏改抽屉(不再铺满全屏)
v5.6.1 汉堡按钮从”看不见”改成显眼的品牌色圆角块
v5.6.3 登录页背景图修复
v5.6.5 登录页底部白条根因修复
v5.6.6 顶部栏右侧加用户头像(有图上图,无图 🐾)
v5.7.0 点头像弹出用户菜单(编辑资料 / 退出登录)
v5.7.1 侧栏三段式布局统一(失败)
v5.7.2 抽屉底部改绝对定位(成功)

二、用户能感知到的三件事

1. 顶部栏:名字和头像装进一个胶囊


之前:[☰] 🐱 狸花云            admin     ← 纯文字
现在:[☰] 🐱 狸花云        ╭──────────╮
                           │admin  🐾│  ← 可点击
                           ╰──────────╯

头像数据来自 /api/profile/me 的 avatar 字段——就是个人主页里设置的那张。登录后异步加载,不阻塞首屏;图片加载失败自动回落到 🐾 emoji,不会空白。

2. 点胶囊弹出用户菜单


┌──────────────────┐
│ admin            │
│ 管理员            │
├──────────────────┤
│ 👤 编辑个人资料    │  → 跳转个人主页
│ 🚪 退出登录        │  → 二次确认后退出
└──────────────────┘

四个交互细节:点胶囊开关菜单、点外部自动收起、退出带二次确认防误触、退出项红色高亮。桌面端不显示这个菜单(侧栏底部有同样的入口),避免两套入口打架。

3. 抽屉三段式:底部永远可见


┌─────────────────────┐
│ 🐱 狸花云            │  top: 0, height: 76px   固定
├─────────────────────┤
│ ▼ 概览              │
│ ▼ 我的              │  top: 76px, bottom: 112px
│ ▼ 系统 7            │  唯一滚动区
│   ...               │
├─────────────────────┤
│ 🐾 admin            │  bottom: 0, height: 112px 固定
│ [🌙 深色] [🚪 退出]  │
└─────────────────────┘

三、一个 height: 100vh 引发的连环坑

这次最值得记录的是抽屉底部消失的排查过程。

第一版:flex 方案(理论正确,实际翻车)


.sidebar {
  position: fixed;
  top: 0; bottom: 0;      /* 靠定位撑满 */
  height: 100vh;          /* 又写死了高度 */
  display: flex; flex-direction: column;
}
.sidebar-nav  { flex: 1 1 auto; min-height: 0; }
.sidebar-foot { flex-shrink: 0; }

手机上底部用户区被挤出屏幕。原因有两个:

1. height 覆盖 bottom 定位。同时写了 top:0; bottom:0; height:100vh,浏览器按 height 算高度,bottom 失效。

2. 100vh 在手机上包含地址栏。iOS Safari 的 100vh 是”地址栏收起后的高度”,地址栏展开时实际可视区更矮——抽屉比屏幕高,底部自然溢出。

第二版:修正 flex(还是翻车)

去掉 height、把 flex: 1 1 auto 改成 flex: 1 1 0%、flex-shrink: 0 改成 flex: 0 0 auto。理论上无懈可击,但部分移动浏览器对 min-height: 0 + flex-basis: 0% 的嵌套收缩计算不一致,底部依然不显示。

第三版:绝对定位(成功)

放弃 flex,三段各自用 top/bottom 精确定位:


@media (max-width: 860px) {
  .sidebar {
    display: block;
    position: fixed;
    top: 0; bottom: 0;
    height: auto;         /* 关键:清掉所有 height */
  }
  .sidebar > .brand {
    position: absolute; top: 0; height: 76px;
  }
  .sidebar > .sidebar-nav {
    position: absolute;
    top: 76px; bottom: 112px;
    overflow-y: auto;
  }
  .sidebar > .sidebar-foot {
    position: absolute; bottom: 0; height: 112px;
  }
}

三段互不干扰,底部高度写死 112px,没有任何依赖浏览器收缩计算的地方。这就是答案。

教训

经验 说明
定位撑满用 top+bottom 不要再叠加 height,会互相覆盖
100vh 在移动端有陷阱 包含地址栏,实际可视区更矮
flex 收缩跨浏览器不可靠 min-height:0 + basis:0 的组合各内核表现不一
绝对定位是最笨但最稳的 不依赖任何布局计算,写死就是写死

四、顺手修的:登录页底部白条

登录页底部莫名出现一条 56px 的白色横条。排查发现是全局样式 body { padding-top: 56px }(给固定顶栏留位置)在登录页没有重置——登录页根本没有顶栏。

修复只有一行:登录页路由下给 body 加 padding-top: 0。这类”全局样式污染特殊页面”的问题,以后每个新页面都要检查一遍。

五、文章体系也更新了

趁着改版,把官网博客的文章全部重写到最新状态:

文章 状态
使用手册 重写:加入安全中心、脚本执行、个人主页、移动端章节
v5 发布公告 重写:覆盖 v5.0 → v5.7.2 全部 30+ 版本
「世界,您好」 删除(WP 默认文章)
测试草稿 ×3 删除

现在博客列表干干净净 4 篇,全是干货。

六、下一步

移动端的主体框架(抽屉、菜单、底部固定)已经稳定,接下来是细节:表格在小屏上的横向滚动、详情页 6 个 Tab 的手机排布、以及把头像显示扩展到服务器列表的”这台属于谁”。


狸花网络 · 让每一台设备都有身份 🐾

💬 留下你的爪印