用 flex 布局撑满视口需设 html/body height:100%、清除 body margin、底部导航与主体同级;iPhone 安全区需 viewport-fit=cover + padding-bottom:env(safe-area-inset-bottom);导航项用 flex:1 1 0 且 min-width:0;backdrop-filter 需 JS 检测并降级。

用 flex 布局撑满视口,避免 fixed 遮挡内容
直接 position: fixed 是最常见也最容易出问题的做法——主内容会钻到导航栏下面,滚动时文字被盖住,软键盘弹出后布局错乱。Flex 方案更可控:把整个页面设为垂直 flex 容器,让主体区域自动“顶住”导航栏底部。
必须做三件事:
-
html和body都要设height: 100%,否则flex: 1没参考高度 - 清除
body默认的margin: 8px,否则 flex 计算会偏差 - 底部导航容器单独抽离,不放进 flex 容器内部,而是和主体同级
结构示例:
<div class="page-content"></div><br><nav class="bottom-nav"></nav>对应 CSS 中
.page-content 设 flex: 1,.bottom-nav 设固定高度(如 height: 60px)。
适配 iPhone 安全区,别只靠 bottom: 0
在 iPhone X 及后续机型上,position: fixed; bottom: 0 会让导航栏沉进手势条里,用户点不到。这不是 bug,是 WebKit 的设计:它默认不把安全区纳入视口计算。
立即学习“前端免费学习笔记(深入)”;
关键不是加 bottom 偏移,而是给导航栏父容器(或导航栏自身)加 padding-bottom:
- 必须在
<meta name="viewport">中包含viewport-fit=cover,否则env(safe-area-inset-bottom)返回0 - 写法是
padding-bottom: 0; padding-bottom: env(safe-area-inset-bottom);,安卓和旧 iOS 自动降级 - 别在
calc()里混用单位,Safari 15.4 之前不支持calc(10px + env(safe-area-inset-bottom)),得拆成两条声明
导航项等分且点击热区一致,别信 flex: 1
对导航项容器设 display: flex; justify-content: space-around 看似简单,但实际中文字长度不同、图标尺寸不一、iOS Safari 对 flex: 1 在 button 内表现异常,都会导致视觉不等宽或点击区域偏移。
稳妥写法:
- 导航项容器用
display: flex,每个子项设flex: 1 1 0; min-width: 0;(min-width: 0是关键,防止 Safari 按文字撑开) - 子项统一用
display: flex; flex-direction: column; align-items: center;,图标文字上下居中 - 如果用
<button>包裹,务必重置其默认padding和background,否则各端表现不一致
毛玻璃效果要检测支持性,不能直接写 backdrop-filter
backdrop-filter 在 iOS Safari 9.0+ 原生支持,但 Android Chrome 直到 114 才默认启用,微信 X5 内核至今不支持。硬写会白屏或模糊异常。
必须先检测再启用:
- JS 检测:
if ('backdropFilter' in document.documentElement.style || '-webkit-backdrop-filter' in document.documentElement.style) - 匹配的 CSS 要用
.supports-backdrop .bottom-nav单独写,否则 fallback 为background: rgba(255, 255, 255, 0.8) -
.bottom-nav自身必须有非全透明背景(如rgba(255,255,255,0.7)),否则滤镜无源可滤 - 确保它的父容器(比如
<body>)下有真实内容,否则滤的是空白
真机测试比模拟器重要得多,尤其是微信内嵌页和低端安卓 WebView —— 这些地方 backdrop-filter 基本等于不存在。


















