【问题标题】:Is it possible to calculate the Viewport Width (vw) without scrollbar?是否可以在没有滚动条的情况下计算视口宽度(vw)?
【发布时间】:2016-02-09 22:44:49
【问题描述】:

如标题所述,是否可以仅在 css 中不使用滚动条来计算 vw

例如,我的屏幕宽度为1920pxvw 返回1920px,太好了。但我的实际身体宽度只有1903px

有没有办法让我只用 css 检索 1903px 值(不仅适用于 body 的直接子代),还是我绝对需要 JavaScript?

【问题讨论】:

  • 但是...滚动条不包含在视口宽度中!?
  • @Danield 抱歉,我更新了我的问题
  • 如果我们谈论的是你放在那里的一些人工滚动条,那么也许你正在寻找这样的东西:width: calc(100vw - scrollbarWidth) 其中 'scrollbarWidth' 是一些固定值,例如 15px
  • @Danield 我实际上需要一个跨浏览器修复,我有每个本机浏览器滚动条的可变宽度
  • 我目前正在使用 Chrome v64 上的 bootstrap 4 处理页面,% 是内部宽度(不包括滚动条), vw 是外部宽度(包括滚动条的宽度)——因此我不能使用 vw而且,就像 OP 一样,我不明白为什么会这样。

标签: css viewport-units


【解决方案1】:

根据the specs,视口相对长度单位不考虑滚动条(事实上,假设它们不存在)。

因此,无论您的预期行为是什么,在使用这些单位时都不能考虑滚动条。

【讨论】:

  • 同样,vw,按照规范,不知道任何滚动条的存在。所以你不能把它们考虑在内。
  • 根据规范,除非溢出是自动的,否则 vw 确实会占用滚动条宽度,然后它就像 vw 值的“隐藏”一样工作。因此,如果页面必须溢出,请将其设置为“滚动”。使用overflow-x 和overflow-y,您可以选择要显示的滚动条。
  • @Kulvar 刚刚在 chrome 中尝试过,将主体设置为 overflow-y: scrolloverflow-y: auto 似乎不会改变 vw 单位的计算值。具体来说,我在我的网站上设置了 3.82vw,我的计算机宽度为 1920px。使用自动溢出,3.82vw = 73.344px,然后我尝试使用溢出滚动,它也输出 73.344px,没有变化,如果你是正确的,它实际上应该输出 72.6946px
  • 100% 考虑到滚动条,所以如果你的情况是 100vw,如果可以的话,把它改成 100%
【解决方案2】:

Webkit 浏览器不包括滚动条,其他浏览器将它们包含在返回的宽度中。 这当然可能会导致问题:例如,如果您使用 ajax 动态生成内容并动态添加高度,Safari 可能会在页面可视化期间从一个布局切换到另一个布局...... 好的,这并不经常发生,但需要注意。 在移动端,问题较少,因为滚动条一般不显示。

也就是说,如果您的问题是在所有浏览器中准确计算没有滚动条的视口宽度,据我所知,一个好方法是:

width = $('body').innerWidth();

之前已设置:

body {
    margin:0;
}

【讨论】:

    【解决方案3】:

    一种方法是使用 calc。据我所知,100% 是包括滚动条的宽度。所以如果你这样做:

    body {
      width: calc(100vw - (100vw - 100%));
    }
    

    你得到 100vw 减去滚动条的宽度。

    如果您想要一个占视口 50% 的正方形(减去 scollbar 宽度的 50%),您也可以使用高度来执行此操作

    .box {
      width: calc(50vw - ((100vw - 100%)/2))
      height: 0
      padding-bottom: calc(50vw - ((100vw - 100%)/2))
    }  
    

    【讨论】:

    • 这太棒了,但不幸的是,只有当您正在调整大小的元素是 body 的直接子元素或与 body 具有相同宽度的元素时才有效(否则 100% 将引用到错误元素的宽度)。在这种情况下,您可以简单地使用百分比。除非我错过了什么?
    • 不适用于 100vw 考虑滚动条确实是个问题的情况——也就是说,当您需要将 100vw 块放入具有固定宽度的容器中时。
    • 数学:100vw - (100vw - 100%) = 100vw - 100vw + 100% = 100% 我错过了什么吗?
    • 不幸的是,这不适用于绝对定位元素,因为 100% 在那里不可用:(
    • @TKoL 在他的解决方案实际上可以解决问题的所有情况下,width:50% 也可以正常工作。 Kamil Kiełczewski 是对的,这个解决方案是没用的。
    【解决方案4】:

    overflow-y 设置为auto 时,vw 单元不会考虑overflow-y 滚动条。

    将其更改为overflow-y: scroll;vw 单元将成为带有滚动条的视口。然后,您可以使用 calc() 从 vw 值中减去滚动条大小。您还可以定义滚动条宽度,使其独立于浏览器。

    唯一需要考虑的缺点。如果内容适合屏幕,则无论如何都会显示滚动条。可能的解决方案是在 javascript 中从 auto 更改为 scroll

    【讨论】:

    • 你的意思是overflow-x
    • 这不是真的。大众单位包括滚动条overflow-y: scroll;
    【解决方案5】:

    我发现它工作的唯一方法是不会用“calc”弄乱你的代码 就是让容器元素大小为100vw;在容器周围添加一个包装器用于溢出-x;这将使容器变成全角,就像滚动条在内容上方一样。

    <!DOCTYPE html>
    <html>
    <head>
    	<style type="text/css">
    	html{ overflow-y: scroll; }
    	html, body{ padding:0; margin: 0;}
    	#wrapper{ overflow-x: hidden; }
    	.row{ width: 100vw; }
    	.row:after{ clear: both; content: ''; display: block; overflow: hidden; }
    	.row-left{ background: blue; float: left; height: 40vh; width: 50vw; }
    	.row-right{ background: red; float: right; height: 40vh; width: 50vw; }
    	</style>
    </head>
    <body>
    
    <div id="wrapper">
    <div class="row">
    	<div class="row-left"></div>
    	<div class="row-right"></div>
    </div>
    </div>
    
    
    </body>
    </html>

    【讨论】:

      【解决方案6】:

      这不是我的解决方案,但可以帮助我创建下拉全角菜单,其相对元素中的绝对值不是完整的跨度。

      我们应该在 :root 中使用 in css var 滚动,然后使用它。

      :root{
       --scrollbar-width: calc(100vw - 100%);
      }
      
      
      div { margin-right: var(--scrollbar-width); }
      

      https://codepen.io/superkoders/pen/NwWyee

      【讨论】:

      • 这仅适用于 div 位于根目录。如果 div 不在根目录下,它会中断。这是因为 calc 在被引用时被解析,相对于它被引用的选择器,而不是它被定义的地方。 codepen.io/Pedr/pen/YorLPM
      【解决方案7】:

      最简单的方法是将 html & body 设置为 100vw:

      html, body{ width:100vw; overflow-x: hidden; overflow-y: auto; margin: 0; }
      

      唯一的问题是如果显示滚动条,最右边会被剪掉一点。

      【讨论】:

        【解决方案8】:

        我通过在文档加载后添加一行 javascript 来定义 CSS 变量来做到这一点:

        document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
        

        然后在 CSS 中,您可以使用 var(--scrollbar-width) 对带有/不带有不同宽度滚动条的不同浏览器进行所需的任何调整。如果需要,您可以对水平滚动条执行类似的操作,将innerWidth 替换为innerHeight,将clientWidth 替换为clientHeight

        【讨论】:

        • 对我来说,返回的大小是需要的两倍。有什么提示吗?给我 16px 但 8px 就足够了...
        • 你在那里回答了你自己的问题。 16px 很可能是滚动条的宽度,但在某些情况下,您需要将其除以 2(例如,当使用负边距创建全宽溢出元素时)。你可以在 CSS 中做到这一点:calc(var(--scrollbar-width) / 2)
        • 这太棒了,这里很容易成为最干净和最正确的解决方案。应该是公认的答案。谢谢!
        • 这是一个非常好的解决方案,但如果我没看错的话,这只有在文档加载的第一页已经有滚动条的情况下才有效。如果它加载一个短页面 --scrollbar-width 将为 0,即使文档变大,
        【解决方案9】:

        如果情况类似于滑块: 正如许多答案中所发布的,宽度 100% 不考虑滚动条,而 100vw 则考虑。如果有许多元素需要占用窗口的宽度并且嵌套在已经具有 100% 窗口宽度的容器内(或者其自然块宽度是这样的),您可以使用:

        • 显示容器的弹性
        • Flex:子元素为 0 0 100%

        【讨论】:

          【解决方案10】:

          100vw = 带有滚动条的屏幕宽度 100% = 没有滚动条的屏幕宽度

          在测量屏幕宽度时总是最好使用 calc(100% - 50px)。即使在滚动条直接可见的 windows 浏览器上,与 macOS 浏览器相比,返回的屏幕宽度也不同。

          【讨论】:

            【解决方案11】:

            不,没有 CSS 中的滚动条就无法计算 vw

            但是,有一种方法可以解决 100vw ruined by the scrollbar on Windows 问题。您必须创建一个全角元素,在本例中为 row--full-width,它从 Flex 容器中突出。此解决方案适用于 Mac 和 Windows:

            HTML:

            <section> 
              <div class="container">
                <div class="row--full-width"></div>
                <div class="row">
                  <div class="card">
                  </div>
                  <div class="card">
                  </div>
                </div>
              </div>
            </section>
            

            正如您在上面的示例中看到的,row--full-width 元素从容器中溢出,即使有滚动条,它也会与标题对齐。

            在 Edge 18 (Win)、Edge 88 (Win/Mac) 和 Chrome 88 (Win/Mac) 上测试。

            【讨论】:

              【解决方案12】:

              复制和粘贴解决方案

              这是一个简单的插入式解决方案,它基于 user11990065 的 answer 设置一个 CSS 变量 --scrollbar-width 并在调整大小时保持更新。 它还会根据 DOMContentLoaded 和加载事件进行计算,因此您不必担心初始渲染阶段的大小变化。

              您可以将其复制并粘贴到您的代码中,因为它是 vanilla JS(或将其包装在“脚本”标签中并将其直接粘贴到您的 HTML 代码中:

              function _calculateScrollbarWidth() {
                document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
              }
              // recalculate on resize
              window.addEventListener('resize', _calculateScrollbarWidth, false);
              // recalculate on dom load
              document.addEventListener('DOMContentLoaded', _calculateScrollbarWidth, false); 
              // recalculate on load (assets loaded as well)
              window.addEventListener('load', _calculateScrollbarWidth);
              

              如果您的页面中有可能显示/隐藏滚动条的动态高度变化,您可能需要查看Detect Document Height Change,您也可以使用它触发高度变化的重新计算。

              由于该值是使用 JS 计算并设置为固定值,因此您可以在 CSS 的计算操作中使用它,如下所示:

              .full-width {
                width: calc(100vw - var(--scrollbar-width));
              }
              

              这将为 .full-width 提供完全可用的宽度。

              【讨论】:

              • 在 Chrome 版本 89 中 window.innerWidthdocument.documentElement.clientWidth 是相同的值
              • @tonitone120 我无法确认,它在 Win 10、Chrome 89.0.4389.114 64 位上运行良好。您使用的是什么操作系统?你确定滚动条是可见的吗?如果它不可见,则大小将为 0,因为这两个值确实相同:)
              • OS Catalina (10.15.6)。滚动条可见。也许我应用了不同的设置或其他东西:/
              • @tonitone120 在 OSX 上,因为滚动条通常只是暂时可见,透明和覆盖(不移动内容或更改显示区域的宽度)它将显示为 0,但那是正确的。将不可见滚动条的屏幕与可见的情况进行比较,内容的宽度保持不变,并没有缩小。这就是滚动条宽度为零的原因,它不会从内容中占用空间,而只是一个叠加层! (如果你总是显示滚动条,它应该不为零 - 在 OSX -> 首选项 -> 常规中设置)
              • 好的,很公平,谢谢你的澄清。那么问题就变成了,我怎样才能得到这个“覆盖”滚动条跨浏览器的宽度?
              【解决方案13】:
              body { overflow: overlay; }
              

              如果您不想让事情过于复杂,在某些情况下这可能就足够了。至少它很好地解决了我的问题,因为内容和视口边缘之间有足够的空白(Windows 滚动条会与最右边的 20 个像素重叠)。

              【讨论】:

                【解决方案14】:

                这可能只是看起来非常“丑陋”。

                首先,您需要运行此脚本以将滚动条宽度转换为 css 变量:

                document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
                

                例如,如果您想要“真正的”80vw,请执行以下操作:

                calc(0.8 * (100vw - var(--scrollbar-width)));
                

                “真实”40vw

                calc(0.4 * (100vw - var(--scrollbar-width)));
                

                【讨论】:

                • 您可以通过将--vw 设置为document.documentElement.clientWidth 来简化此操作,然后像calc(0.8 * var(--vw)) 一样使用它。
                猜你喜欢
                • 2016-11-06
                • 1970-01-01
                • 2020-04-26
                • 2011-07-28
                • 2018-01-15
                • 1970-01-01
                • 2012-01-10
                • 1970-01-01
                相关资源
                最近更新 更多