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

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

如何避免这个问题?当我第一次听说viewport-height时,我很兴奋,我认为我可以使用它来固定高度块,而不是使用javascript,但现在我认为唯一的方法实际上是javascript与一些调整大小事件…

您可以在:示例站点看到问题

有人能帮助我/建议一个CSS解决方案吗?


简单测试代码:

/* 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 should 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>


当前回答

我们有新的视口单元lvh, svh和dvh来拯救。这在最新的谷歌I/O 2022网络作品视频中得到了证明。

您可能希望继续使用dvh,以便浏览器在滚动时适应移动设备的隐藏选项卡。它的工作方式类似于宽度dvw, lvw和svw单位。

这是视频中的一个简洁的插图:https://youtu.be/Xy9ZXRRgpLk?t=982

我能用吗?

这是目前工作在我的Chrome金丝雀与标志“实验功能”启用。

其他回答

不幸的是,这是故意的……

这是一个众所周知的问题(至少在safari mobile中),这是故意的,因为它可以防止其他问题。Benjamin Poulain回复了一个webkit漏洞:

This is completely intentional. It took quite a bit of work on our part to achieve this effect. :) The base problem is this: the visible area changes dynamically as you scroll. If we update the CSS viewport height accordingly, we need to update the layout during the scroll. Not only that looks like shit, but doing that at 60 FPS is practically impossible in most pages (60 FPS is the baseline framerate on iOS). It is hard to show you the “looks like shit” part, but imagine as you scroll, the contents moves and what you want on screen is continuously shifting. Dynamically updating the height was not working, we had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, use the large view size. From the data we had, using the larger view size was the best compromise. Most website using viewport units were looking great most of the time.

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在2016年也变成了这样:

https://groups.google.com/a/chromium.org/forum/ !主题/ blink-dev / BK0oHURgmJ4 https://developers.google.com/web/updates/2016/12/url-bar-resizing

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

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

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

他们只添加了6个媒体查询来适应全高度元素,它应该可以工作,因为它是完全由CSS实现的。

编辑等待:我现在无法测试它,但我会回来报告我的结果。

看起来CSS修复是不可靠的,JS一个工作得很好,但元素在用户打开页面时跳跃。

我解决了这个问题使用JS从其他答案+淡出动画隐藏跳跃。

这并不适合所有的用例,但对于其中一些用例,比如必须在底部的按钮,可能是一个很好的解决方案。

你可以试着给出位置:fixed;上图:0;底部:0;属性到您的容器。

看看这个答案:https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

// First we get the viewport height and we multiple it by 1% to get a value for a vh unit let vh = window.innerHeight * 0.01; // Then we set the value in the --vh custom property to the root of the document document.documentElement.style.setProperty('--vh', `${vh}px`); // We listen to the resize event window.addEventListener('resize', () => { // We execute the same script as before let vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`); }); body { background-color: #333; } .module { height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */ 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; } <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>