刘海屏设备下使用vh单位布局时,如何避免内容被刘海遮挡?

Tr° 梓涵 阅读 97

我在开发一个全屏显示的页面时遇到了问题,用100vh设置高度在普通手机上没问题,但在iPhone 14 Pro的刘海屏上底部内容被刘海区域遮挡了一部分,看起来就像这样:


标题栏
内容区域

我尝试过用padding-bottom调整,也查了apple的viewport-fit=cover参数,但修改后页面边缘会出现横向滚动条。有没有什么方法能准确计算刘海屏的可用高度?或者需要配合JavaScript检测刘海区域的尺寸?

我来解答 赞 14 收藏
二维码
手机扫码查看
2 条解答
增梅 Dev
刘海屏这个问题确实挺烦人的,特别是iPhone那个动态岛出来之后更复杂了。我之前也被坑过几次,现在告诉你几个靠谱的解决方案。

首先你要明白为什么100vh会出问题。vh单位是基于整个视口高度的,但刘海屏的实际可用高度会比视口高度小。苹果提供了safe-area-inset-*系列CSS变量来处理这个问题。

推荐的做法是用CSS的env()函数配合viewport-fit=cover:

1. 在meta标签里加上viewport-fit=cover
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">


2. 然后CSS里这样写:
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
min-height: 100vh;
/* 这个100vh是回退方案 */
min-height: calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
}


如果你需要精确控制整个页面的高度,可以这样:
.container {
height: calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));
overflow-y: auto;
}


如果遇到横向滚动条问题,通常是padding导致的,可以这样修复:
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}


实在不行的情况下再用JavaScript检测,但能CSS解决的就不要用JS:
// 获取安全区域高度
function getSafeAreaHeight() {
return window.innerHeight -
parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sat')) -
parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sab'));
}


几个注意事项:
1. env()和constant()在iOS11+都支持,但新版本用env()就行
2. 测试时一定要在真机上测,模拟器有时候不准
3. 安卓手机也有类似的坑,但处理方式不同
4. 如果用了fixed定位的元素,也要加上safe-area-inset的padding

记住永远不要相信100vh在移动设备上的表现,这玩意坑了无数前端开发者。我上周还在为一个华为手机的圆角屏适配熬夜改代码...
点赞 3
2026-03-07 01:01
爱敏
爱敏 Lv1
viewport-fit=coverenv(safe-area-inset-top)env(safe-area-inset-bottom) 就行。

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">


然后样式:

body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}


横向滚动条是其他地方出了问题,检查下宽高设置。
点赞 15
2026-02-01 10:02