移动浏览器中的CSS3 100vh不恒定

我有一个非常奇怪的问题…在每一个浏览器和手机版本,我遇到了这种行为:

  • 当你开始滚动页面时,所有的浏览器都有一个顶部菜单,当你加载页面(例如显示地址栏)时,它会向上滑动。
  • 100vh仅在视口的可见部分计算,所以当浏览器栏向上滑动100vh时(以像素为单位)
  • 所有的布局重新绘制和重新调整,因为尺寸已经改变
  • 用户体验不好的跳跃效果

怎么能避免这个问题? 当我第一次听到视口高度,我很兴奋,我想我可以使用它的固定高度块istead使用JavaScript,但现在我认为唯一的方法来做到这一点实际上是一些resize事件的JavaScript …

您可以在示例站点查看问题

任何人都可以帮我/build议一个CSS解决scheme?


简单的testing代码:

/* maybe i can track the issue whe it occours... */ $(function(){ var resized = -1; $(window).resize(function(){ $('#currenth').val( $('.vhbox').eq(1).height() ); if (++resized) $('#currenth').css('background:#00c'); }) .resize(); }) 
 *{ margin:0; padding:0; } /* this is the box which sould keep constant the height... min-height to allow content to be taller than viewport if too much text */ .vhbox{ min-height:100vh; position:relative; } .vhbox .t{ display:table; position:relative; width:100%; height:100vh; } .vhbox .c{ height:100%; display:table-cell; vertical-align:middle; text-align:center; } 
 <div class="vhbox" style="background-color:#c00"> <div class="t"><div class="c"> this div height should be 100% of viewport and keep this height when scrolling page <br> <!-- this input highlight if resize event is fired --> <input type="text" id="currenth"> </div></div> </div> <div class="vhbox" style="background-color:#0c0"> <div class="t"><div class="c"> this div height should be 100% of viewport and keep this height when scrolling page </div></div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 

不幸的是这是故意的

这是一个众所周知的问题(至less在Safari移动中),这是故意的,因为它可以防止其他问题。 本杰明·普兰回答了一个webkit的bug :

这完全是故意的。 为了达到这个效果,我们做了很多工作。 🙂

基本的问题是:可见区域在您滚动时dynamic变化。 如果我们相应地更新CSS视口高度,则需要在滚动过程中更新布局。 不仅这看起来像狗屎,而且在大多数页面上以60 FPS的速度进行操作实际上是不可能的(60 FPS是iOS上的基准帧速率)。

很难向你展示“看起来像狗屎”的部分,但想象你滚动,内容移动,你想要在屏幕上不断移动。

dynamic更新高度不起作用,我们有几个select:在iOS上删除视口单位,匹配像iOS 8之前的文档大小,使用小视图大小,使用大视图大小。

从我们的数据来看,使用较大的视图尺寸是最好的折衷scheme。 大多数使用视口单元的网站大部分时间看起来都很棒。

Nicolas Hoizey已经研究了很多: https ://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile -browsers.html

没有修复计划

此时,除了避免在移动设备上使用视口高度,您可以做的事情不多。 移动Chrome浏览器似乎也想要适应这一点,虽然不知道他们是否会遵循 。

对于我build立的许多网站来说,客户端会要求一个100vh的横幅,就像你发现的那样,当你开始滚动的时候,它会在移动设备上产生一个糟糕的“跳跃”体验。 这就是我在所有设备上解决问题的平滑一致体验:

我首先将我的横幅元素CSS设置为height:100vh

然后我使用jQuery来获取横幅元素的像素高度,并使用这个高度应用内联样式。

 var viewportHeight = $('.banner').outerHeight(); $('.banner').css({ height: viewportHeight }); 

这样做可以解决移动设备上的问题,因为当页面加载时,横幅元素被设置为100vh使用CSS,然后jQuery通过将内联CSS放在我的横幅元素上,从而阻止它在用户开始滚动时resize。

但是,在桌面上,如果用户调整浏览器窗口的大小,我的横幅元素将不会resize,因为由于上面的jQuery,它现在具有固定的像素高度。 为了解决这个问题,我使用Mobile Detect来为我的文档添加一个“移动”类。 然后我把上面的jQuery包装在一个if语句中:

 if ($('body').hasClass('mobile')) { var viewportHeight = $('.banner').outerHeight(); $('.banner').css({ height: viewportHeight }); } 

因此,如果用户在移动设备上,则“我的页面”主体上显示“mobile”类,并执行上面的jQuery。 因此,我的横幅广告素材只能在移动设备上应用内嵌的CSS,而在桌面上,原始的100vh CSS规则仍然保留。

我刚刚发现我devise的一个networking应用程序在iPhone和iPad上有这个问题,并发现一篇文章build议使用针对特定苹果设备的媒体查询来解决这个问题。

我不知道是否可以在这里分享这篇文章中的代码,但地址是这样的: http : //webdesignerwall.com/tutorials/css-fix-for-ios-vh-unit-bug

退出文章:“使用针对旧版iPhone和iPad分辨率的媒体查询,将元素高度与设备高度相匹配”。

他们只添加了6个媒体查询来适应全高度的元素,并且应该在完全实现CSS的情况下工作。

编辑挂起:我现在无法testing,但我会回来报告我的结果。