不能用 height: 100vh 做全屏导航,因其将地址栏高度计入视口导致底部被截断;应改用 position: fixed + inset: 0(或 top/right/bottom/left: 0)严格贴合可见视口,并配 overflow-y: auto 和 z-index: 1000 确保可滚动与层级正确。

为什么不能用 height: 100vh 做全屏导航
在 iOS Safari 上,vh 会把地址栏高度算进视口,导致导航底部被截断——用户滚动到底部时看到空白或切掉最后一行菜单。这不是渲染延迟,是浏览器对视口的定义缺陷,改 height 值或加 min-height 都无效。
真正可靠的方式是脱离文档流:position: fixed + inset: 0(现代写法),或显式写 top: 0; right: 0; bottom: 0; left: 0。这样它才严格贴合当前可见视口边界,不随页面滚动偏移,也不受地址栏缩放影响。
-
inset: 0在 Chrome/Firefox/Safari 15.4+ 支持良好;旧版 Safari 需回退到四边归零写法 - 必须配
overflow-y: auto,否则小屏长菜单无法滚动,用户卡死在顶部 -
z-index: 1000是底线值,低于这个容易被 modal、toast 或第三方组件盖住
如何用 transform 实现平滑展开/收起
别碰 height 过渡:内容高度为 auto 时,CSS 无法计算过渡起止值,动画直接失效或跳变。用 transform 则无此限制,还能触发硬件加速,更顺滑。
实操建议:
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 初始状态设
transform: translateY(-100%),展开时改为transform: translateY(0) - 过渡只写在
transform上:transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1) - JS 控制只需切换一个类名(如
nav-open),不要直接操作style属性 - 收起后加
pointer-events: none,避免误触;展开时恢复为auto
怎么锁住背景滚动又不破坏 iOS 回弹
只给 body 加 overflow: hidden 在 iOS 上会导致页面“回弹”——手指松开后页面猛地往上弹一截,体验极差。这是因为 Safari 对 overflow: hidden 的实现不完整。
正确做法是双保险:
- 菜单打开时,给
body加overflow: hidden; position: fixed; top: 0; width: 100% - 关闭时,立刻移除这些样式,并手动
scrollTo(0, window.scrollY)补偿位置偏移 - 别依赖
document.body.style.overflow = 'hidden'单条语句,它在 iOS 上不可靠
焦点管理为什么不是可选项
视觉上菜单“盖住了”页面,但键盘用户按 Tab 仍能跳进背后不可见区域,或焦点丢失到页面外——这在无障碍测试中直接失败,也违反 WCAG 2.1 标准。
必须同步处理三件事:
- 菜单激活时,用 JS 拦截
Tab键,在菜单内循环聚焦所有tabindex="0"或可交互元素(a、button) - 按
ESC必须关闭菜单,且关闭后焦点要回到触发按钮(调用triggerButton.focus()) - 菜单关闭时,若原焦点不在按钮上,需记录并恢复(用
document.activeElement+focus())
最常被跳过的其实是焦点回归逻辑——很多人只做了展开约束,却没管收起后的焦点去向,结果用户按完 ESC 后不知道光标在哪,只能重按 Tab 扫描整个页面。


















