为什么 vw 将滚动条作为视口的一部分?

Why does vw include the scrollbar as part of the viewport?

我正在尝试建立一个网站,其中包含许多等宽和等高的框。例如,我的页面有 2 个并排的大小相等的框。

简单的解决方案是将宽度和高度设置为 50vw。在有滚动条之前,这很好用。我在 Google 上搜索了几个小时,不明白为什么 vw 和 vh 会将滚动条作为视口的一部分。

这是我的问题的示例

HTML

<div class="container">
    <div class="box red"></div>
    <div class="box green"></div>
</div>
<div class="lotta-content"></div>

CSS

body {
    margin: 0;
    padding: 0;
}

.container {
    width: 100vw;
}

.box {
    float: left;
    width: 50vw;
    height: 50vw;
}

.red {
    background-color: red;
}

.green {
    background-color: green;   
}

.lotta-content {
    height: 10000px;   
}

注意不需要的水平滚动条

https://jsfiddle.net/3z887swo/

一个可能的解决方案是使用百分比表示宽度,但使用 vw 表示高度,但它永远不会是一个完美的盒子,这不是世界上最糟糕的事情,但仍然不理想。这是一个示例

https://jsfiddle.net/3z887swo/1/

有谁知道为什么 vw/vh 将滚动条作为视口的一部分?另外,如果有人有比我自己更好的解决方案,我很乐意听到。我正在寻找一个纯粹的 CSS 解决方案。我宁愿没有 javascript.

如果视口单位不 包括 会很方便导致滚动条,但它毕竟是显示尺寸(屏幕)。不过,请使用伪元素查看此解决方案:

http://www.mademyday.de/css-height-equals-width-with-pure-css.html

在您的示例中也构成一个正方形:

https://jsfiddle.net/3z887swo/4/

.box {
    float: left;
    width: 50%;
}

.box::before {
    content: "";
    display: block;
    padding-top: 100%;
}

编辑 - 如果有人想知道为什么会这样(垂直填充响应原始元素的宽度)...规范中基本上就是这样定义的:

The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'.

http://www.w3.org/TR/CSS2/box.html#padding-properties


在看到我自己的答案后,我认为它需要一些改进。语义歧义是我在顶部用 "cause" 替换单词 "include" 的原因。因为更重要的是 vw 单位只考虑视口大小 - 包括任何滚动条和 导致 溢出和滚动条在另一个方向上,当它的宽度被添加到 100vw 时(使视口加上滚动条宽度所需的总 space 超出屏幕)。

对于此处的问题,处理 vw 单位的最佳方式可能是尽可能避免使用它们,因为它们与桌面浏览器不太兼容(没有叠加滚动条) .

我删除了包含 CSS 变量的想法,尽管它看起来很有希望。

我有不同的答案,觉得有必要分享我的沮丧

因为标准制定者很愚蠢

(委员会,一般来说,总是)

一个简单(简单)的解决方法是始终保持滚动条并对其进行处理

html,body {margin:0;padding:0}
html{overflow-y:scroll}

(对使用 vh 的布局使用 overflow-x

我相信他们真的在这件事上把狗搞砸了。

html { overflow-x: hidden; }

似乎有效

这个问题很老了,上面回答得很好,所以我将专注于获取滚动条宽度,然后用于计算元素宽度,这就是我来到这里的原因。希望这会对其他 Google 员工有所帮助。

草率的CSS解决方案

我开始根据下面的计算编写纯 CSS 解决方案,但是一旦您开始考虑可变宽度容器内的元素,尤其是当它们不是可见宽度的 100% 时,calc 函数开始变得复杂和不可读。

对于任何感兴趣的人,根元素 (<html>) 上的 calc(假设文档是全宽且不更宽)将为您提供滚动条宽度,或者当没有显示滚动条时为 0 .

calc( 100vw - 100% );

稳健的解决方案

就我个人而言,我不会在这个问题上争论 CSS。使用正确的工具完成工作:

(function get_scrollbar_width() {

    // Get window width including scrollbar.
    const withScrollBar = window.innerWidth;
    
    // Get window width excluding scrollbar.
    const noScrollBar = document.querySelector("html").getBoundingClientRect().width;
    
    // Calc the scrollbar width.
    scrollbarWidth = parseInt((withScrollBar - noScrollBar), 10) + 'px';

    // Update the CSS custom property value.
    let root = document.documentElement;
    root.style.setProperty('--scrollbar', scrollbarWidth);
    
})();
:root {
    --scrollbar: 0px;
}

body {
    overflow: scroll;
}

.demobox {
    display: grid;
    grid: auto / var(--scrollbar) max-content;
    width: calc(10em + var(--scrollbar) );
    margin: 0 auto;
}

.demobox > div {
    background: red;
}

.demobox > p {
    padding: 1em;
    text-align: center;
    width: 10em;
}
<div class="demobox">
    <div></div>
    <p>
        This red grid cell represents the scrollbar width as set
        on the CSS custom property by the JavaScript function.
    </p>
</div>