一行代码修复100vh bug | 京东云技术团队

你知道奇怪的移动视口错误(也称为100vh bug)吗?或者如何以正确的方式创建全屏块?

一、100vh bug

什么是移动视口错误?

你是否曾经在网页上创建过全屏元素?只需添加一行 CSS 并不难:

css 复制代码
.my-page {
     height: 100vh
} 

1vh是视口高度的1% ,正是我们所需要的。但当我们在移动设备上测试时,就会出现问题。移动浏览器的视口可以动态改变,但值保持不变。因此在移动浏览器中vh变成静态值并且不反映视口的实际高度。

在下图中,可以看到移动屏幕的两种状态:

带有隐藏的地址栏

具有可见的地址栏

核心问题是移动浏览器(Chrome 和 Safari)有一个"有用"的功能,地址栏有时可见,有时隐藏,从而改变视口的可见大小。这些浏览器并没有随着视口高度的变化而将高度调整100vh为屏幕的可见部分,而是将100vh地址栏设置为隐藏地址的浏览器高度。结果是,当地址栏可见时,屏幕的底部将被切断,从而违背了100vh最初的目的。

有什么方法可以解决这个问题?

二、常规修复

1. CSS + Javascript

使用的解决方案涉及使用CSS 自定义属性和一些Javascript。

简而言之,我们监听resize事件并在每次窗口大小更改时设置--vh自定义属性(窗口高度的1% ):

核心功能代码:

javascript 复制代码
//首先获得视口高度并将其乘以1%以获得1vh单位的值
 let vh = window.innerHeight * 0.01
 // 然后,我们将------vh自定义属性中的值设置为文档的根
  document.documentElement.style.setProperty('--vh', `${vh}px`)
 // 监听resize事件 视图大小发生变化就重新计算1vh的值
  window.addEventListener('resize', () => {
     // 执行与前面相同的脚本
     let vh = window.innerHeight * 0.01
     document.documentElement.style.setProperty('--vh', `${vh}px`)
 })
ini 复制代码
<div class="module">
  <div class="module__item">20%</div>
  <div class="module__item">40%</div>
  <div class="module__item">60%</div>
  <div class="module__item">80%</div>
  <div class="module__item">100%</div>
</div>
css 复制代码
body {
  background-color: #333;
}

.module {
  height: 100vh; /* 不支持自定义属性时的回退操作*/
  height: calc(var(--vh, 1vh) * 100);
  margin: 0 auto;
  max-width: 30%;
}

.module__item {
  align-items: center;
  display: flex;
  height: 20%;
  justify-content: center;
}

.module__item:nth-child(odd) {
  background-color: #fff;
  color: #F73859;
}

.module__item:nth-child(even) {
  background-color: #F73859;
  color: #F1D08A;
}

2. 使用 -webkit-fill-available

css 复制代码
.my-page { 
    background-color: #ffffff; 
    min-height: 100vh; 
    min-height: -webkit-fill-available; 
    overflow-y: scroll; 
    padding-bottom: 50px;
 }

此方法chrome浏览器中在某些情况下使用会有问题。

因此引出下文第三种方法。

3. postcss-100vh-fix

当然,你也可以使用第三方库来进行修复,具体使用可查看其官网 postcss-100vh-fix。

它适用于 Chrome( -webkit-fill-available 在某些情况下只会在 Chrome 中导致问题)、iOS/iPad/MacOS Safari 和 所有其他浏览器 。纯CSS解决方案,无需JS。

css 复制代码
body {
  /* Footer will be hidden on iOS Safari because of bottom panel */
  height: 100vh;
}
css 复制代码
body {
  height: 100vh;
}

/* Avoid Chrome to see Safari hack */
@supports (-webkit-touch-callout: none) {
  body {
    /* The hack for Safari */
    height: -webkit-fill-available;
  }
}

此方法不适用于部分高度,例如height: 90vh 或height: calc(100vh - 60px)

三、更好的方法

根据CSS Values 4 规范:视口相对长度,我们可以使用新的视口单位。

有一个dvh单位可以完成全部工作。它始终会适应视口大小。最后,浏览器支持如下:

有了这个很酷的功能,解决方案变得非常简单,只需要一行 CSS:

css 复制代码
.my-page {
     height: 100dvh
}

可以在此了解更多的动态视口单元信息,如:dvw、dvh、dvi、dvb、dvmin 和 dvmax等。

结论

如今,CSS 发展迅速,对解决前端问题有很大帮助。该dvh单位是制作视口相关高度的最佳选择。这是一个非常简单而强大的 CSS 功能,可以让你的工作变得更加轻松。

作者:京东保险 张洁

来源:京东云开发者社区 转载请注明来源

相关推荐
前端爆冲8 分钟前
项目中无用export的检测方案
前端
热爱编程的小曾36 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin1 小时前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox