Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html CSS3 100vh在移动浏览器中不是常量_Html_Css_Viewport Units - Fatal编程技术网

Html CSS3 100vh在移动浏览器中不是常量

Html CSS3 100vh在移动浏览器中不是常量,html,css,viewport-units,Html,Css,Viewport Units,我有一个很奇怪的问题。。。在每个浏览器和手机版本中,我都会遇到这种行为: 加载页面时,所有浏览器都有一个顶部菜单(例如显示地址栏),当您开始滚动页面时,该菜单会向上滑动 100vh有时仅在视口的可见部分计算,因此当浏览器栏向上滑动时,100vh增加(以像素为单位) 所有布局重新绘制和调整,因为尺寸已更改 对用户体验的不良跳跃效应 如何避免这个问题?当我第一次听说viewport height时,我很兴奋,我想我可以将它用于固定高度块,而不是使用javascript,但现在我认为唯一的方法是使

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

  • 加载页面时,所有浏览器都有一个顶部菜单(例如显示地址栏),当您开始滚动页面时,该菜单会向上滑动
  • 100vh有时仅在视口的可见部分计算,因此当浏览器栏向上滑动时,100vh增加(以像素为单位)
  • 所有布局重新绘制和调整,因为尺寸已更改
  • 对用户体验的不良跳跃效应
如何避免这个问题?当我第一次听说viewport height时,我很兴奋,我想我可以将它用于固定高度块,而不是使用javascript,但现在我认为唯一的方法是使用带有一些调整大小事件的javascript

您可以在以下位置看到问题:

有人能帮我推荐一个CSS解决方案吗


简单测试代码:

/*也许我可以跟踪问题发生的时间*/
$(函数(){
var resized=-1;
$(窗口)。调整大小(函数(){
$('.#currenth').val($('.vhbox').eq(1.height());
如果(++调整大小)$('#currenth').css('background:#00c');
})
.resize();
})
*{margin:0;padding:0;}
/*
这是一个保持高度不变的盒子。。。
最小高度,允许内容在文本过多时高于视口
*/
.vhbox{
最小高度:100vh;
位置:相对位置;
}
.vhbox.t{
显示:表格;
位置:相对位置;
宽度:100%;
高度:100vh;
}
.vhbox.c{
身高:100%;
显示:表格单元格;
垂直对齐:中间对齐;
文本对齐:居中;
}

此div高度应为视口的100%,并在滚动页面时保持此高度

此div高度应为视口的100%,并在滚动页面时保持此高度
不幸的是,这是故意的…

这是一个众所周知的问题(至少在safari mobile中),这是故意的,因为它可以防止其他问题:

这完全是故意的。我们花了不少功夫才达到这个效果

基本问题是:可见区域在滚动时会动态变化。如果我们相应地更新CSS视口高度,我们需要在滚动期间更新布局。这不仅看起来像狗屎,而且在大多数页面中,以60 FPS的速度这样做几乎是不可能的(60 FPS是iOS上的基准帧速率)

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

动态更新高度不起作用,我们有几个选择:在iOS上放置视口单位,像iOS 8之前那样匹配文档大小,使用小视图大小,使用大视图大小

从我们拥有的数据来看,使用较大的视图大小是最好的折衷方案。大多数使用视区单位的网站在大多数时候看起来都很棒

Nicolas Hoizey对此进行了大量研究:

未计划修复

此时,除了避免在移动设备上使用“视口高度”,您可以做的事情不多。2016年,Chrome也改为:


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

我不知道是否可以在此处共享该文章中的代码,但地址如下:

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

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


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

对于我创建的许多站点,客户端会要求提供100vh横幅,正如您所发现的,当您开始滚动时,它会在移动设备上造成糟糕的“跳跃”体验。这就是我如何解决问题,在所有设备上实现平稳一致的体验:

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

然后,我使用jQuery获取banner元素的高度(以像素为单位),并使用此高度应用内联样式

var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });
这样做可以解决移动设备上的问题,因为当页面加载时,banner元素使用CSS设置为100vh,然后jQuery通过在我的banner元素上放置内联CSS来覆盖它,从而在用户开始滚动时阻止它调整大小

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

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

因此,如果用户在移动设备上,则“mobile”类出现在我的页面主体上,并执行上面的jQuery。因此,我的banner元素将只在移动设备上应用内联CSS,而在桌面上,原来的100vh CSS规则仍然有效。

由于我是新手,我无法对其他答案发表评论

如果有人正在寻找一个解决方案来实现这一点(并且可以使用javascript——目前看来这是实现这一点所必需的),那么这种方法对我来说非常有效,它也说明了移动定位的变化。我在示例代码中使用Jquery,但在vanillaJS中应该是可行的

-首先,我使用一个脚本来检测设备是触摸还是悬停。赤裸裸的例子:

if ("ontouchstart" in document.documentElement) {
    document.body.classList.add('touch-device');

} else {
    document.body.classList.add('hover-device');
}
这将根据稍后可用于高度脚本的设备类型(悬停或触摸)向body元素添加类

-接下来,使用此代码设置设备在负载和方向改变时的高度:

if (jQuery('body').hasClass("touch-device")) {
//Loading height on touch-device
    function calcFullHeight() {
        jQuery('.hero-section').css("height", $(window).height());
    }

    (function($) {
        calcFullHeight();

        jQuery(window).on('orientationchange', function() {
            // 500ms timeout for getting the correct height after orientation change
            setTimeout(function() {
                calcFullHeight();
            }, 500);

        });
    })(jQuery);

} else {
    jQuery('.hero-section').css("height", "100vh");


}
-设置超时,以便设备在方向更改时正确计算新高度。如果有
var vhHeight = $("body").height();
var chromeNavbarHeight = vhHeight - window.innerHeight;
$('body').css({ height: window.innerHeight, marginTop: chromeNavbarHeight });
# html
<body>
  <div class="content">
    <!-- Your stuff here -->
  </div>
</body>

# css
.content {
  height: 80vh;
}
html { height: 100vh; }

body {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100vw;
}

/* this is the container you want to take the visible viewport  */
/* make sure this is top-level in body */
#your-app-container {
  height: 100%;
}
:root {
  --devHeight: 86vh; //*This value changes
}

.div{
    height: calc(var(--devHeight)*0.10); //change multiplier to suit required height
}
max-height: calc(100vh - 120px);
  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);
}
// 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;
}
.browser-has-chin {
  @media screen and (max-device-width: 767px){
    // offset with padding or something
  }
}