场景
这种情况多半是出现在使用了vh或者vw这种单位的情况。
原因
横向滚动条导致高度错误
假如我搞了一个上下布局,上面导航栏,下面内容区域。
比如导航栏固定高度60px。
内容区域使用下面的计算高度。
height: calc(100vh - 60px);
由于产生了横向滚动条,元素的实际高度发生变化。
在edge上,打开开发者工具,鼠标悬停在calc上,可以看到100vh对应924px。
如果在页面上选取元素,会发现滚动条不包含在元素区域。
$0.offsetHeight
// 输出 909
$0.scrollHeight
// 输出 921
这个差异就是因为滚动条。
100vh包含滚动条,100%不包含滚动条。
类似于scrollHeight和offsetHeight的区别
解决
使用100%
这种方法使用场景比较少,大家都不是傻子,既然能用100%为什么还用vh呢?
vh的场景一般是,外部容器没有限定大小,比如没有设置高度100%,或者只设置了min-height: 100%,这会导致内部的height百分比无效。
如果是min-height的问题,可以通过下面的方法解决。
juejin.cn/post/740913…
使用js自定义css变量计算正确的vh
function setViewportHeight() {
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
// 初始化
setViewportHeight();
// 响应窗口大小变化(包括旋转、展开开发者工具等)
window.addEventListener('resize', setViewportHeight);
下面是加了防抖的写法
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
function setViewportHeight() {
let vh = document.body.offsetHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
// 初始化
setViewportHeight();
// 使用防抖包装 resize 回调,例如延迟 100ms
const debouncedSetViewportHeight = debounce(setViewportHeight, 100);
window.addEventListener('resize', debouncedSetViewportHeight);
.my-element {
height: calc(var(--vh, 1vh) * 100 - 60px);
}
border等隐性高度
AI分析不出这种问题,可能他直接认为所有元素都是border-box。
而且使用playwright他也睁眼说瞎话,说没有滚动条。
import '@unocss/reset/tailwind-v4.css'
unocss中的重置样式,不包含这个,因此假如想要减小心智负担,可以手动加重置样式。
* {
box-size: border-box;
}