我有一个很奇怪的问题…在每个浏览器和手机版本中,我都遇到了这种行为:
当你加载页面时,所有的浏览器都有一个顶部菜单(例如显示地址栏),当你开始滚动页面时,它会向上滑动。
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>
React用useEffect和useState挂钩解决方案
function App() {
const [vh, setVh] = useState(window.innerHeight);
useEffect(() => {
const updateVh = () => {
setVh(window.innerHeight);
};
window.addEventListener('resize', updateVh);
return () => window.removeEventListener('resize', updateVh);
}, []);
return (
<div style={{ height: vh }}>
{vh} px
</div>
);
}
演示:https://jsfiddle.net/poooow/k570nfd9/
React用useEffect和useState挂钩解决方案
function App() {
const [vh, setVh] = useState(window.innerHeight);
useEffect(() => {
const updateVh = () => {
setVh(window.innerHeight);
};
window.addEventListener('resize', updateVh);
return () => window.removeEventListener('resize', updateVh);
}, []);
return (
<div style={{ height: vh }}>
{vh} px
</div>
);
}
演示:https://jsfiddle.net/poooow/k570nfd9/
我们有新的视口单元lvh, svh和dvh来拯救。这在最新的谷歌I/O 2022网络作品视频中得到了证明。
您可能希望继续使用dvh,以便浏览器在滚动时适应移动设备的隐藏选项卡。它的工作方式类似于宽度dvw, lvw和svw单位。
这是视频中的一个简洁的插图:https://youtu.be/Xy9ZXRRgpLk?t=982
我能用吗?
这是目前工作在我的Chrome金丝雀与标志“实验功能”启用。
因为我是新人,我不能对其他答案发表评论。
如果有人正在寻找一个答案,使这个工作(可以使用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");
}
-Timeout设置,以便设备在方向改变时正确计算新的高度。如果没有超时,根据我的经验,高度是不正确的。500毫秒可能有点过分,但对我来说很有效。
如果浏览器覆盖CSS的100vh,则-100vh在hover-devices上是一个备用选项。