根本原因是父容器缺乏可计算高度,align-items: center依赖交叉轴空间才能生效;常见表现是元素贴顶、iOS地址栏收起时跳动,需用inset: 0+display: flex+min-height: 100vh+height: 100%组合保障。

为什么 align-items: center 写了却还是不居中
根本不是 Flex 属性写错了,而是父容器没拿到“真实高度”。align-items: center 只在交叉轴有可用空间时才生效;如果父容器计算出的高度是 0px 或远小于视口,它就无处可居中。
常见现象包括:弹窗紧贴顶部、缩放后突然上移、iOS Safari 中地址栏收起时内容跳动。DevTools 里一查,父层(比如 .modal-overlay)高度经常是 0 或异常值。
-
html和body必须显式设height: 100%,否则子级的height: 100vh无继承基准 - 仅用
position: fixed不够,必须配inset: 0(或top: 0; right: 0; bottom: 0; left: 0),否则脱离文档流后尺寸丢失 -
100vh在 iOS Safari 中会随地址栏/软键盘动态变化,导致高度突变,不能单独依赖
父容器必须写的四条关键样式
遮罩层(.modal-overlay)不是“铺满就行”,它是整个居中逻辑的锚点。缺一不可:
-
position: fixed—— 锚定视口,滚动时不偏移 -
inset: 0—— 比width: 100vw; height: 100vh更可靠,绕过老 WebView 解析 bug -
display: flex; justify-content: center; align-items: center—— 双轴居中,弹窗无需transform或absolute -
min-height: 100vh; height: 100%—— 关键组合:min-height保底一屏,height: 100%在键盘弹出等场景下能回退到实际html高度
漏掉任意一条,都可能在某个机型或交互状态下失效。
立即学习“前端免费学习笔记(深入)”;
.modal-content 的尺寸与滚动怎么设才不崩
弹窗本体要“交出控制权”:它不能抢高度,也不能锁死尺寸,否则会破坏 Flex 居中流和滚动能力。
- 禁用
height、min-height、flex: 1—— 这些会让它脱离 Flex 的居中计算,同时导致滚动失效 - 用
max-height: calc(100vh - 120px)替代80vh—— 预留标题、按钮等固定区域,比硬写百分比更稳 - 必须加
overflow-y: auto,且只作用于.modal-content自身,外层.modal-overlay保持overflow: hidden(默认) - 宽度推荐
width: 100%; max-width: 500px—— 小屏自适应,大屏不撑爆,避免横向滚动
iOS Safari 下的 100vh 抖动怎么防
这不是 bug,是 Safari 对视口单位的历史性误判:地址栏收起时,100vh 会被当成“含地址栏的总高”,导致容器过高、内容偏上。单纯 JS 监听 resize 并不够——软键盘弹出时事件不触发,且存在延迟。
- 首选方案:用
min-height: 100vh; height: 100%双保险,配合html, body { height: 100% } - 次选方案:改用
100dvh(dynamic viewport height),但注意兼容性 —— Chrome 105+ / Safari 16.4+ 支持,旧版需降级 fallback - 绝对不要给
.modal-content加height: 100%或flex: 1—— 这会让它强行占满父容器高度,滚动直接消失,居中也失效
真正难的不是写对那几行 CSS,而是理解每一层高度从哪来、到哪去。Flex 居中本身很干净,崩坏全发生在高度传递链的某一个断裂点上。


















