问答中心分类: HTMLCSS3 100vh在移动浏览器中不恒定
0
匿名用户 提问 10小时 前

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

  • 加载页面时,所有浏览器都有一个顶部菜单(例如显示地址栏),当您开始滚动页面时,该菜单会向上滑动。
  • 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;
}
this div height should be 100% of viewport and keep this height when scrolling page
    
    
    
  



  
  this div height should be 100% of viewport and keep this height when scrolling page
29 Answers
0
Saurabh Jain 回答 10小时 前

你可以试试min-height: -webkit-fill-available;在css中,而不是100vh.应该解决

Tammy Tee 回复 10小时 前

我会离开min-height: 100vh;作为后备方案-webkit-fill-available不支持。

JoniVR 回复 10小时 前

@Tammyte是对的,最好保持min-height: 100vh;在Firefox这样的浏览器上(至少在桌面上,iOS使用webkit,无论使用何种浏览器),它都会崩溃。

Maros 回复 10小时 前

这就引入了Android Chrome上的键盘问题。隐藏键盘后,它似乎保持了较小的高度。

RwwL 回复 10小时 前

这是一个非常好的解决方案,但在iOS 13中似乎有所改变-我在第一节的底部看到了额外的空间,但它在iOS 12.x的Safari中完全可以正常工作codepen.io/RwwL/pen/PowjvPq(你必须把它分叉,然后在iOS上的CodePen调试模式下查看,才能真正理解我的意思)。

Joe Seifi 回复 10小时 前

谢谢,这太干净了!顺便说一句,我结束了使用这个版本,因为我的应用程序一开始依赖于高度非零height: 100vh; max-height: -webkit-fill-available;

TheCat 回复 10小时 前

由于Chrome v84,不再支持webkit填充/

Etienne Bruines 回复 10小时 前

虽然这种方法是迄今为止最简单的,但它确实存在一些问题,即当手机键盘弹出时不重新计算。

squarecandy 回复 10小时 前

这太棒了。我很确定订单在这里很重要。我们很习惯这样做:-webkit-bleedingedgethingy: 1; bleedingedgethingy: 1;因此,当常规版本进入规范时,优先考虑。但在这里,您希望特定于供应商的设置覆盖正常设置height: 100vh; height: -webkit-fill-available;而不是相反。

soshimee 回复 10小时 前

有趣的是,它如何解释边界大小并将其减去。非常有用。

rexxar 回复 10小时 前

就像Bootstrap4一样,html样式的“height:100vh”和类“vh-100”对body似乎也起作用

0
Andreas Herd 回答 10小时 前

在我的应用程序中,我这样做(typescript和嵌套PostCs,因此相应地更改代码):

const appHeight = () => {
    const doc = document.documentElement
    doc.style.setProperty('--app-height', `${window.innerHeight}px`)
}
window.addEventListener('resize', appHeight)
appHeight()

在css中:

:root {
    --app-height: 100%;
}

html,
body {
    padding: 0;
    margin: 0;
    overflow: hidden;
    width: 100vw;
    height: 100vh;

    @media not all and (hover:hover) {
        height: var(--app-height);
    }
}

它至少可以在chrome手机和ipad上运行。不起作用的是,当你在iOS上将应用程序添加到主屏幕并更改方向几次时——不知何故,缩放级别会干扰innerHeight值,如果我找到解决方案,我可能会发布更新。
演示

Andreas Herd 回复 10小时 前

我想添加一个警告,即“@media not all and(hover:hover){”不是检测移动浏览器的防弹方法。请随意使用其他方法。

Zach Gollwitzer 回复 10小时 前

我非常喜欢这种方法。我要说的一点是关于事件侦听器的使用。这会导致重新绘制页面,我仅在某些情况下使用它,因为用户必须看到正确的视口(即主页初始视图)

async await 回复 10小时 前

@AndreasHerd这是sass,不是css?我不熟悉将媒体查询嵌套在body selector区域内

Andreas Herd 回复 10小时 前

@AsyncWait我在本例中使用了PostCs,但大多数css后处理器支持嵌套css。不过,您可以很容易地将其展平为常规css。

0
Patryk Janik 回答 10小时 前

对我来说,这样的伎俩很管用:

height: calc(100vh - calc(100vh - 100%))
FF_Dev 回复 10小时 前

它与身高:100%不同吗?

Patryk Janik 回复 10小时 前

是的,100vh是视口高度(您的设备)的100%,当纯100%仅填充所有可用的父区域时(父块可以具有例如50px的高度,它将仅填充到此父高度)。总之。

Eli 回复 10小时 前

这个简单的技巧确实有效,虽然地址栏没有隐藏,但它比其他解决方案更好。向上投票。

user1383029 回复 10小时 前

非常感谢。非常感谢。非常感谢。这是迄今为止最干净的解决方案。在Firefox(桌面和移动)、Chrome(桌面和移动)和Safari(移动)中测试

SleepWalker 回复 10小时 前

这实际上与write相同height: 100%因为它转化为100vh - 100vh + 100%因此,这种方法可以称为“根本不使用vh”。重要提示:为了能够使用height: 100%,则必须将该高度从根元素传播到所有子元素,直到目标元素。有时候可能太难了

0
manuel-84 回答 10小时 前

看看这个答案: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>
FrEaKmAn 回复 10小时 前

非常好的解决方案。就我而言,我并没有使用ponyfill,而是在逻辑上,对于所有桌面站点,我都使用100vh,而对于移动设备,我使用var(我们在移动世界中并没有IE11)。

ecc521 回复 10小时 前

唯一适用于嵌套元素的解决方案。在其他需要替换几百个实例的情况下,您可以(至少在大多数情况下)匹配regexp(-)?([\d.]+)vh并用calc(var(-vh)*$1$2)替换

0
Sarath Ak 回答 10小时 前

您可以通过添加以下脚本和样式来实现这一点

function appHeight() {
  const doc = document.documentElement
  doc.style.setProperty('--vh', (window.innerHeight*.01) + 'px');
}

window.addEventListener('resize', appHeight);
appHeight();

风格

.module {
  height: 100vh; /* Fallback for browsers that do not support Custom Properties */
  height: calc(var(--vh, 1vh) * 100);
}
sstauross 回复 10小时 前

本文对此进行了详细描述:com/the trick to viewport units on mobile/…

Imran Bughio 回复 10小时 前

这在iPhone XR Chrome上不起作用,底部导航栏仍然覆盖着100vh元素