用Flex实现兼容性好的全屏布局
手动 calc(100dvh - ...) 在 iOS 上很容易踩坑,推荐改用 Flex 布局,让浏览器自己分配剩余空间:
<div class="page"> <header class="header">头部</header> <div class="query">查询条件</div> <div class="content">内容区(自动撑满剩余高度)</div> <footer class="footer">底部</footer> </div>
* { margin: 0; padding: 0; box-sizing: border-box; /* 关键!避免 padding 撑大高度 */ } html, body {
height: 100vh; /* pc端用 100vh,外层锁死 */
height: 100dvh; /* 手机上会出现地址栏等一些内容,所以用 100dvh,外层锁死 */ overflow: hidden; /* 禁止页面级滚动 */ } .page { display: flex; flex-direction: column; height: 100dvh; } .header, .query, .footer { flex-shrink: 0; /* 固定高度,不被压缩 */ } .content { flex: 1; /* 自动吃掉所有剩余空间 */ overflow-y: auto; /* 内容区内部滚动 */ -webkit-overflow-scrolling: touch; /* iOS 流畅滚动 */ }
优点:
-
不用算高度,header/footer 多高都无所谓
-
自动适配 iOS 地址栏、安全区域
-
代码简洁,维护方便
CSS Flexbox 相关的属性简要说明一下:
1. flex-shrink: 0
lex-shrink 表示当父容器空间不足时,子元素是否允许缩小以及缩小的比例。默认值是 1,表示允许缩小。
flex-shrink: 0表示 不允许子元素缩小,即使父容器空间不足,子元素也保持自身的宽度或高度,不会被压缩。
举个简单例子:
.item { flex-shrink: 0; }
这样设置后,如果父容器宽度不足,.item 不会缩小,反而可能导致父容器出现滚动条或溢出。
2. flex: 1
flex 是 flex-grow, flex-shrink, flex-basis 的简写,写法是:
flex: [flex-grow] [flex-shrink] [flex-basis];
而 flex: 1 等同于:
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
它的含义是:
flex-grow: 1:允许该元素在父容器有剩余空间时,按比例增长,占满所有剩余空间。flex-shrink: 1:当空间不足时,也允许该元素缩小。flex-basis: 0:在计算伸缩时,初始大小为 0,然后根据剩余空间分配。
简言之,flex: 1 表示该元素会尽可能地填满父容器剩余空间,并根据空间变化动态伸缩。
总结
| 属性 | 作用说明 | 使用场景示例 |
|---|---|---|
flex-shrink: 0 |
不允许缩小,保持本身大小 | 不希望元素变小,比如固定按钮大小 |
flex: 1 |
允许伸缩,填满剩余空间 | 常用作弹性伸展,如自适应内容区 |
手机端视图窗口的简要说明:
以采用动态计算视口高度的办法:
let vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`);
然后用 CSS:
height: calc(var(--vh, 1vh) * 100);
此外,最新的浏览器标准引入了更精确的视口单位:
svh(small viewport height):最小视口高度(不考虑地址栏、工具栏等)lvh(large viewport height):最大视口高度(地址栏、工具栏隐藏时)dvh(dynamic viewport height):动态视口高度,会随着地址栏显示隐藏动态调整
但是,这些单位的支持情况仍在逐步完善中,具体使用时仍需查看目标设备和浏览器的支持情况。手机端浏览器中100vh 包含地址栏和工具栏,而且还是可见显示区域。
浙公网安备 33010602011771号