【问题标题】:Prevent 100vw from creating horizontal scroll防止 100vw 创建水平滚动
【发布时间】:2015-08-09 23:02:17
【问题描述】:

如果一个元素设置为width: 100vw; 并且有一个垂直滚动条,则该元素的宽度将等于视口加上滚动条的宽度。

是否可以防止这种情况发生?

是否可以在不禁用整个页面的水平滚动的情况下防止这种情况发生?除了更改我的 css/标记以使元素 100% 的身体宽度之外,我想不出任何东西。

在 Windows 8.1 上的 Chrome 版本 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 中测试

这里是要求的代码:

Example

html

<div class="parent">
    <div class="box"></div>
</div>
<div class="tall"></div>

css

body { margin: 0; }
html { box-sizing: border-box; }
*, *::before, *::after {
    box-sizing: inherit;
    position: relative;
}
.parent {
    background: rgba(0, 0, 0, .4);
    height: 100px;
    width: 5rem;
    margin-bottom: 25px;
}

.box {
    position: absolute;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, .4);
    height: 50px;
    width: 100vw;
}

.tall {
    height: 100rem;
}

【问题讨论】:

  • 这可能有很多原因。发布您的代码。
  • 也许将边距设置为 0 ?
  • 你试过溢出:隐藏?
  • 这个错误的存在仍然让我大吃一惊,而且还没有采取任何措施。这显然不是任何人希望他们的浏览器做的事情。

标签: css scroll


【解决方案1】:

基本上答案是否定的,如果您有一个垂直滚动条,则无法使 100vw 等于可见视口的宽度。以下是我为这个问题找到的解决方案。

警告: 我尚未测试这些解决方案是否支持浏览器


tl;dr

如果您需要一个元素为可见视口的 100% 宽度(视口减去滚动条),您需要将其设置为主体的 100%。如果有垂直滚动条,你不能用 vw 单位来做。


1.将所有祖先元素设置为静态位置

如果您确保所有.box 的祖先都设置为position: static;,则将.box 设置为width: 100%;,这样它将是主体宽度的100%。但这并不总是可能的。有时您需要其中一位祖先是position: absolute;position: relative;

Example

2。将元素移到非静态祖先之外

如果您无法将祖先元素设置为 position: static;,则需要将 .box 移到它们之外。这将允许您将元素设置为主体宽度的 100%。

Example

3.移除垂直滚动条

如果您不需要垂直滚动,您可以通过将&lt;html&gt; 元素设置为overflow-y: hidden; 来移除垂直滚动条。

Example

4.移除水平滚动条 这并不能解决问题,但可能适用于某些情况。

&lt;html&gt;元素设置为overflow-y: scroll; overflow-x: hidden;会阻止水平滚动条出现,但100vw元素仍会溢出。

Example

视口百分比长度规范

视口百分比长度与 初始包含块。当初始的高度或宽度 包含块被更改,它们会相应地缩放。然而, 当根元素的overflow值为auto时,任何滚动 条形图假定不存在。请注意,初始包含 块的大小受滚动条的影响 视口。

似乎存在一个错误,因为当在根元素上将溢出设置为自动时,vw 单位应该只包括滚动条宽度。但我尝试将根元素设置为 overflow: scroll; 并没有改变。

Example

【讨论】:

    【解决方案2】:

    这是一种更成熟的解决该错误的方法,因为它仍然存在于现代浏览器中。设置 overflow-x: hidden 在许多情况下可能会导致问题或不受欢迎。

    此处提供完整示例:http://codepen.io/bassplayer7/pen/egZKpm

    我的方法是确定滚动条的宽度并使用calc()100vw 减少滚动条的数量。这有点复杂,因为在我的例子中,我从一个定义了 with 的盒子中拉出内容的宽度,所以我也需要声明边距。

    关于以下代码的几点说明:首先,我注意到 20px 似乎是滚动条的一个相当广泛的幻数。我使用 SCSS 变量(它不必是 SCSS)和 @supports 之外的代码作为后备。

    此外,这并不能保证永远不会有滚动条。由于它需要 Javascript,因此未启用该功能的用户将看到水平滚动条。你可以通过设置overflow-x: hidden 来解决这个问题,然后在 Javascript 运行时添加一个类来覆盖它。

    完整的 SCSS 代码:

    $scroll-bar: 20px;
    
    :root {
        --scroll-bar: 8px;
    }
    
    .screen-width {
      width: 100vw;
      margin: 0 calc(-50vw + 50%);
    
        .has-scrollbar & {
            width: calc(100vw - #{$scroll-bar});
            margin: 0 calc(-50vw + 50% + #{$scroll-bar / 2});
        }
    
        @supports (color: var(--scroll-bar)) {
            .has-scrollbar & {
                width: calc(100vw - var(--scroll-bar));
                margin: 0 calc(-50vw + 50% + (var(--scroll-bar) / 2));
            }
        }
    }
    

    只需删除 #{$scroll-bar} 引用并替换为 px 值即可将上述内容转换为纯 CSS

    然后这个 Javascript 将设置 CSS 自定义属性:

    function handleWindow() {
        var body = document.querySelector('body');
    
        if (window.innerWidth > body.clientWidth + 5) {
            body.classList.add('has-scrollbar');
            body.setAttribute('style', '--scroll-bar: ' + (window.innerWidth - body.clientWidth) + 'px');
        } else {
            body.classList.remove('has-scrollbar');
        }
    }
    
    handleWindow();
    

    附带说明一下,Mac 用户可以通过转到系统偏好设置 -> 常规 -> 显示滚动条 = 始终进行测试

    【讨论】:

      【解决方案3】:

      填充和边框可能会干扰。保证金也可以。使用box-sizing 计算包含这些属性的宽度。并且可能从宽度中删除边距(如果有)。

      * {
          -webkit-box-sizing: border-box;
          -moz-box-sizing: border-box;
          box-sizing: border-box;
      }
      body {
          margin: 0; /* interferes with 100vw */
      }
      .parent {
          width: 100vw;
          max-width: 100%; /* see below */
      }
      .box {
          width: 100%; /* For those good old-fashioned browsers with no vw or calc() support */
          width: -webkit-calc(100vw - [your horizontal margin, if any]);
          width: -moz-calc(100vw - [your horizontal margin, if any]);
          width: calc(100vw - [your horizontal margin, if any]);
          max-width: 100%
      }
      

      如果有回流导致滚动条出现在初始视口宽度计算之后,您似乎必须添加max-width: 100%;。在没有干扰滚动条的浏览器(iOS、OS X、IE 11 Metro)中似乎不会发生这种情况,但会影响所有其他浏览器。

      【讨论】:

      • 如果你要使用前缀来调整大小,你肯定也需要一些前缀来计算。
      • @BramVanroy 绝对。 -moz-calc() 和 -webkit-calc() 可用。
      • 我不明白这是如何解决问题的。我希望元素等于 100vw 减去滚动条宽度,而不是 100vw 减去它的父级边距。您是说大众汽车在计算中增加了利润吗?因为那听起来不对。
      • @NiklasBrunberg 这是我所期待的行为,但事实并非如此。我会试着整理一个例子。
      • @NiklasBrunberg 嗯,但是 max-width 100% 你只是覆盖了在 vw 中设置的宽度。因此,您可以将宽度更改为 100%。我希望宽度实际上是 100vw(父级不一定是视口的 100%。我更改了 jsfiddle 以显示不是 100% 宽度的父级的问题。
      【解决方案4】:

      我也在为此苦苦挣扎,我还认为 CSS 变量是解决方案。 IE11 不支持 CSS 变量,所以我尝试了其他方法:

      我通过计算滚动条的宽度来修复它:从window(包括滚动条)的宽度中减去body(不包括滚动条)的宽度。我用它来将它添加到 100% 的 body 中,参见 plusScrollBar 变量。

      JS:

          // calculate width of scrollbar and add it as inline-style to the body
      var checkScrollBars = function() {
          var b = $('body');
          var normalw = 0;
          var scrollw = 0;
          normalw = window.innerWidth;
          scrollw = normalw - b.width();
      
          var plusScrollBar = 'calc(' + '100% + ' + scrollw + 'px)'
          document.querySelector('body').style.minWidth = plusScrollBar;
      }();
      

      CSS:

      html{
          overflow-x: hidden;
      }
      

      为什么我喜欢这个:考虑到并非所有滚动条的宽度都相同或根本被视为节省空间。 :)

      【讨论】:

      • 仅供参考 - 使用它需要调整大小/去抖动,否则你的身体会变成固定宽度,在调整大小/设备旋转时会暴露出来。
      • 100% 是流动的 ;)
      【解决方案5】:

      max-width 属性与width:100vw 一起使用,它解决了我的问题。

      这是我用的。

      .full{
           height: 100vh;
           width: 100vw;
           max-width: 100%;
          }
      

      基本上它的作用是固定视口的最大宽度,从而消除水平滚动。

      更多@https://www.w3schools.com/cssref/pr_dim_max-width.asp

      max-width 属性定义元素的最大宽度。

      如果内容大于最大宽度,会自动 改变元素的高度。

      如果内容小于最大宽度,max-width 属性无效。

      【讨论】:

      • 为我工作。但是,width: 100% 具有相同的效果。我看不出这有什么好处。我错过了什么吗?
      • 这对我有用,谢谢!这是最简单的方法,我认为这将被标记为正确答案。
      【解决方案6】:

      我遇到了同样的问题,添加后已解决:

      html, body { overflow-y: auto; }
      

      我添加了评论:

      /* this fixes a 100vw issue, removing the horizontal scrollbar when it's unneeded */
      

      它至少适用于 Firefox、Chrome、Opera 和 Internet Explorer 11(我为 IE 使用了浏览器)。

      不过,我不知道它为什么有效,以及它是否适用于所有情况。

      编辑: 水平滚动条消失了,但我注意到它仍然可以使用光标键和触摸屏水平滚动...

      【讨论】:

      • 一个小时或更多试图解决这个问题和一个简单的溢出:auto!!!
      • 这似乎适用于 Firefox,但不适用于 Chrome(截至 2020 年 5 月 26 日的最新版本)
      【解决方案7】:

      overflow-x: clip; 完成这项工作。

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。您可以在帮助中心找到更多关于如何写好答案的信息:stackoverflow.com/help/how-to-answer。祝你好运?
      【解决方案8】:

      我遇到了同样的问题。当我将 vw 单位更改为百分比时,水平滚动条消失了。

      【讨论】:

      • 将其设置为其父级的百分比。它只是对你有用,因为那一刻父母的幸运情况恰好是屏幕宽度。情况并非总是如此,并且对解决大众汽车的问题没有任何帮助。
      【解决方案9】:

      如果您在一个框架(例如 ASP.NET)中工作,其中可能有一个父元素环绕 html,那么将 html 的 max-width 设置为 100% 将解决问题,而无需使用“创可贴” " 解决方案overflow-x: hidden.

      html {
         max-width: 100%;
      }
      

      【讨论】:

        【解决方案10】:

        具有width: 100vw 的元素仅在其父元素之一具有水平填充时才会导致水平滚动条。否则它应该很适合。

        检查这个小提琴:http://jsfiddle.net/1jh1cybc/ .parent2 有一个填充,这会导致内部 .box 突破它的父宽度。

        编辑:

        在您的情况下,我猜您的body 有余量。用你的代码检查这个小提琴并尝试删除 body css 规则:http://jsfiddle.net/1jh1cybc/1/

        【讨论】:

        • 我的身体没有边距。查看我刚刚添加到问题中的 jsfiddle。它是你修改的。
        • 你的第二个例子没有垂直滚动条,所以没有水平溢出。
        • 我已经调整了我的第二个例子,给了盒子 1000px 的高度,仍然没有水平滚动条:jsfiddle.net/1jh1cybc/3
        • 我看过你的小提琴,但我没有水平滚动条,只有垂直滚动条...dl.dropboxusercontent.com/u/9719519/2015-05-27/Fiddle.jpg
        • 您使用的是什么浏览器/操作系统?我根本不认识滚动条。
        【解决方案11】:

        这是我的工作:

        div.screenwidth{
            width:100%;  /* fallback for browsers that don't understand vw or calc */
            width: calc(100vw - 17px); /* -17 because vw is calculated without the scrollbar being considered & 17px is width of scrollbars */
            position:relative;  /* use this if the parent div isn't flush left */
            right: calc((100vw - 17px - 100% )/2);
        

        }

        【讨论】:

        • 没有滚动条的设备怎么办?该元素最终将短 17px。 17px 也不是所有滚动条的通用宽度。我刚刚签入了我当前版本的 chrome,滚动条是 15px。
        • 是的,它短了 17px,但是定位居中它,我个人(因为没有实际的解决方案)更喜欢使用两侧 8px 的间隙而不是水平滚动。
        【解决方案12】:

        我在我的网站上通过将 body{overflow-x:hidden} 添加到相关页面来解决此问题。

        也适用于您的示例。

        【讨论】:

        • 我在回答中提到了这个问题。这不是一个解决方案,但它可能适用于某些您不介意丢失部分元素的情况,因为 100vw 元素仍会溢出。阅读我的答案中的#4
        【解决方案13】:

        下面是我对100vw添加水平滚动问题的解决方案:

        html {
        width: calc(100% + calc(100vw - 100%));
        overflow-x: hidden;
        }
        
        .box {
        width: calc(100% + calc(100vw - 100%));
        }
        

        【讨论】:

        • 您的答案中有很多无用的混乱。这是一个同样有效的简单版本:html{overflow-x:hidden;}
        • 您的回复对 OP 的问题没有任何帮助。我建议你再读一遍。
        • 我建议您查看您的答案。您在答案中写的内容与 html{width:100%;overflow-x:hidden;} .box{width:100vw;} 之间几乎没有功能上的区别,除了很多无用的数学运算。
        • {width: 100%} 和 {width: 100vw} 不一样。也许这就是你的误解的来源。
        • 100% + (100vw - 100%) = 100% + 100vw - 100% = 100vw。除了隐藏这个答案有效的事实之外,数学没有任何作用,因为你的身体上有溢出-x。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-09
        相关资源
        最近更新 更多