安全区域
cloud.tencent.com/developer/a…
背景
-
硬件设计变化:
- 全面屏设计:手机取消了物理按键,采用了更大的显示区域
- 刘海屏/打孔屏:顶部有摄像头和传感器的凹槽区域
- 底部手势区域:取消物理Home键后,改用手势操作
- 圆角屏幕:屏幕四角采用圆角设计
-
安全区域的必要性:
- 避免内容遮挡:防止页面重要内容被刘海、圆角、手势区域等遮挡
- 保证可操作性:确保交互元素(如按钮)不会被系统手势区域干扰
- 防止误触操作:底部按钮可能与系统手势冲突
- 提升用户体验:让用户可以方便地进行系统操作(如返回手势、Home手势等)
- 视觉体验:内容过于贴近边缘,影响美观
-
安全区域的位置:
- 顶部:适配刘海屏/状态栏
- 底部:适配手势操作区域(如底部工具栏、虚拟导航栏)
- 左右两侧:适配圆角和可能的手势区域
css变量
安全区域边界有4个预定义变量:主要用于处理移动设备底部安全区域的适配问题
- safe-area-inset-left:安全区域距离左边边界距离
- safe-area-inset-right:安全区域距离右边边界距离
- safe-area-inset-top:安全区域距离顶部边界距离
- safe-area-inset-bottom:安全区域距离底部边界距离
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
具体来说:
- padding-bottom: constant(safe-area-inset-bottom); 和 padding-bottom: env(safe-area-inset-bottom); 这两行代码是用来处理全面屏手机(比如iPhone X及以后的机型)底部安全区域的内边距。
- 为什么需要这个:在全面屏手机上,底部会有一个手势区域或者虚拟Home键区域,这个区域不应该被应用的内容遮挡,否则会影响用户体验
使用了两个版本的语法:
- constant() 是早期版本的语法
- env() 是新版本的语法
- 同时使用是为了保证更好的兼容性
使用场景
iPhoneX对比起以前其他的手机,屏幕顶部变成了留海屏,底部取消了物理按键改成了小黑条,这种改动导致了web开发中页面上新的适配问题。
比如一些需要贴在底部的按钮,和呼起的tabBar和底部弹出框,在iphoneX上就会出现被小黑条遮挡内容,或者页面上出现白色空隙的问题。
<head>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover" name="viewport"/>
</head>
body {height: 100vh;}
/* 你的贴底元素↓ */
.container {
position: absolute;
bottom: 0;
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
...
}
vh问题
为什么设置安全区域还是没有成功
正常而言:1vw 等于1/100的视口宽度 (Viewport Width),1vh 等于1/100的视口高度 (Viewport Height)
但是,在移动端,情况就不太一样了。100vh 不总是等于一屏幕的高度。有的时候,100vh 高度会出现滚动条。
根因在于:
- 很多浏览器,在计算 100vh 的高度的时候,会把地址栏等相关控件的高度计算在内
- 同时,很多时候,由于会弹出软键盘等操作,在弹出的过程中,
100vh
的计算值并不会实时发生变化!
这也就变相导致了许多基于 100vh
想实现的效果无形中会产生很多问题。
解决
function setVh() {
// Calculate 1vh in pixels
const vh = window.innerHeight * 0.01;
// Set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
// Set the initial value
setVh();
// Recalculate on window resize
window.addEventListener('resize', setVh);
JavaScript 代码:
setVh
函数用于计算视口高度,并将其设置为 CSS 变量--vh
。window.innerHeight * 0.01
计算出1vh
的像素值。document.documentElement.style.setProperty('--vh',
${vh}px)
将计算出的值设置为--vh
变量。- 页面加载时调用
setVh
函数,确保初始值正确。 - 监听
resize
事件,在窗口大小改变时重新计算视口高度。
.full-height {
height: calc(var(--vh, 1vh) * 100);
background-color: lightblue;
}
CSS 样式:
- 我们在
:root
中定义了一个 CSS 变量--vh
,初始值为100%
。 - 在
.full-height
类中,我们使用calc(var(--vh, 1vh) * 100)
来设置高度,这样可以确保高度是动态计算的视口高度。