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

当你加载页面时,所有的浏览器都有一个顶部菜单(例如显示地址栏),当你开始滚动页面时,它会向上滑动。 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>


当前回答

不要使用推荐的方法,如-webkit-fill-available。 我花了一整天的时间来修复这个“bug”。

当你的应用程序被一个带有“下巴”的浏览器加载时,添加一个类。

JavaScript

// Angular example but applicable for any JS solution
@HostBinding('class.browser-has-chin') browserHasChin: boolean = false;

public ngOnInit(): void {
    this.browserHasChin = this._isMobileSafari();
}

private _isMobileSafari() {
    return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/) ? true : false;
}

CSS

.browser-has-chin {
  @media screen and (max-device-width: 767px){
    // offset with padding or something
  }
}

注: 在跨浏览器兼容性方面,-webkit-fill-available道具存在一些重大问题。

我能够让它在Chrome和iOS Safari中工作,以修复下巴/高度计算问题。然而,它破坏了Android Chrome和Firefox也有bug。

似乎-webkit-fill-available在某种程度上是匆忙加入webkit的,也许是苹果偶然采用的,作为下巴/高度计算的修复?

它依赖于内在的大小,这是不安全的使用。

其他回答

对于我所创建的许多网站,客户端都会要求100vh的横幅,正如你所发现的那样,当你开始滚动时,它会导致糟糕的“跳跃”体验。这就是我如何在所有设备上获得流畅一致的体验:

我首先设置我的横幅元素CSS的高度:100vh

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

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

这样做解决了移动设备上的问题,当页面加载时,使用CSS将横幅元素设置为100vh,然后jQuery通过在我的横幅元素上放置内联CSS来阻止它在用户开始滚动时调整大小。

然而,在桌面上,如果用户调整他们的浏览器窗口大小,我的横幅元素不会调整大小,因为它现在有一个固定的高度像素设置由于上述jQuery。为了解决这个问题,我使用Mobile Detect在我的文档正文中添加了一个“Mobile”类。然后我将上面的jQuery封装在if语句中:

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

因此,如果用户在移动设备上,“mobile”类就会出现在我的页面主体上,并且会执行上面的jQuery。所以我的横幅元素只会得到内联CSS应用在移动设备上,同时在桌面上,原来的100vh CSS规则仍然存在。

看看这个答案: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>

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

下面是我在React应用程序中使用的一个方法。

iPhone 11 Pro和iPhone Pro Max - 120px

iPhone 8 - 80px

max-height: calc(100vh - 120px);

这是一个折衷方案,但相对简单

对我来说,这种把戏成了一种工作:

height: calc(100vh - calc(100vh - 100%))