首页 > 其他分享 >一行代码修复100vh bug | 京东云技术团队

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

时间:2023-12-19 11:03:20浏览次数:39  
标签:浏览器 vh bug 视口 100vh height 京东 CSS

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

一、100vh bug

什么是移动视口错误?

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

.my-page {
     height: 100vh
} 

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

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

带有隐藏的地址栏

具有可见的地址栏

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

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

二、常规修复

1. CSS + Javascript

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

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

核心功能代码:

//首先获得视口高度并将其乘以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`)
 })
<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>
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


.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。

body {
  /* Footer will be hidden on iOS Safari because of bottom panel */
  height: 100vh;
}
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:

.my-page {
     height: 100dvh
}

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

结论

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

作者:京东保险 张洁

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

标签:浏览器,vh,bug,视口,100vh,height,京东,CSS
From: https://www.cnblogs.com/jingdongkeji/p/17913195.html

相关文章

  • 如何利用烛龙和谷歌插件优化CLS(累积布局偏移) | 京东云技术团队
    简介CLS衡量的是页面的整个生命周期内发生的每次意外布局偏移的最大突发性_布局偏移分数_。布局变化的发生是因为浏览器倾向于异步加载页面元素。更重要的是,您的页面上可能存在一些初始尺寸未知的媒体元素。这种组合意味着浏览器在加载完成之前无法确定单个元素将占用多少空间。因......
  • 测试用例设计方法六脉神剑——第五剑:化气为型,场景用例破云 | 京东物流技术团队
    1引言前几篇文章主要针对单点功能的测试用例设计方法展开介绍。然而,当拿到一个测试任务时,并非先关注某个功能的细节测试,而是先要使用场景法对主要业务流程和主要功能展开测试,当业务场景没有问题后,再使用等价类、边界值、判定表等方法对细节功能进行测试(先整体后细节)。2概念及原理......
  • Zulip: Debugging Zulip-Mobile: Server + Android + IOS
    https://github.com/abaelhe/zuliphttps://github.com/abaelhe/zulip-mobileDebuggingSeeingwhattheappisdoingisanessentialpartofdevelopment.Avarietyoftoolsareavailabletohelpusdothat.Index:OfficialadvicefromReactNativeupstreamDeb......
  • FirebirdSql.Data.FirebirdClient.FbDataAdapter的bug吗
    在连接Firebird4数据库时,使用以下: FbDataAdapterda=newFbDataAdapter(sql,this.cnstring); DataTabledt=newDataTable(); da.Fill(dt); returndt;在一直的相像中,FbDataAdapter在接收到连接字符串时,会自动创建一个Connection并Open使用,用完再Close,即不需......
  • shell补-特殊玩法-shell编程debug
    shell补-特殊玩法-shell编程debugdebug思想debug测试单步执行脚本自个调试,用注释,或者echo自个打印输出啥的,就这么搞bash-x整个脚本调试set与开关debug(适用于脚本或者命令行都可以)set-x开始debugset+x结束debug##在脚本启用set;set-x开始,set+x结尾......
  • debug解决实际问题--python
    简述:原代码一直报错,提示索引超出范围"IndexError:tupleindexoutofrange"一、原代码:#-*-coding:utf-8-*-importpymysql,datetime#获取框架合约数据defframe_treaty_get(frame_treaty_no_list):frame_treaty_list=[]forframe_treaty_noinframe_t......
  • 过瑞数中的高级debugger
    (function(){vara=newDate();debugger;returnnewDate()-a>100;}())这种debugger如果是用‘一律不在此处暂停’是过不去的。 要在浏览器的控制台中执行并阻止debugger语句,你可以使用JavaScript的toString()方法来重写原函数的定义。这种方法......
  • IDEA工具第八篇:6个让你爱不释手的Debug技巧
    一、条件断点循环中经常用到这个技巧,比如:遍历1个大集合或者数组的过程中,想让断点停在某个特定值。【操作】debug运行指定方法后|在Debug小红点上右键|Condition输入条件|Done二、返回上一步该技巧最适合特别复杂的方法套方法的场景,好不容易跑起来,一不小心手一抖,“下一......
  • C++(cmake-build-debug 和 cmake-build-release)
    cmake-build-debug和cmake-build-release是两个默认的构建目录名称,通常在使用CMake构建项目时生成。以下是它们的主要作用和区别:1.cmake-build-debug:这是一个用于调试构建的默认构建目录名称。在这个目录下,CMake会生成包含调试信息的可执行文件,以方便在调试器中进行调试......
  • _DEBUG预处理器定义问题
    release状态编译了一个dll,但运行报assert错误,看了下系统库的源码,是在"#ifdefined_DEBUG"条件编译下的代码报出来的,疑惑release为什么还有_DEBUG状态,搜了代码、查看了预处理器定义都是没有的。后询问了大佬,原来如此:  查看微软官方说明,确实:Thecompilerdefines _DEBUG......