【问题标题】:How to prevent scrollbar from repositioning web page?如何防止滚动条重新定位网页?
【发布时间】:2010-11-27 22:11:11
【问题描述】:

我有一个 DIV 居中对齐的网站。现在,有些页面需要滚动,有些则不需要。当我从一种类型移动到另一种类型时,滚动条的出现将页面移动到一边几个像素。有没有什么办法可以避免这种情况而不在每个页面上显式显示滚动条?

【问题讨论】:

标签: html css


【解决方案1】:

我认为不会。但是用overflow: scroll 设计body 应该可以。不过,你似乎知道这一点。

【讨论】:

  • 听起来不错...强制页面始终显示滚动条,无论是否需要,...然后页面类型之间没有视觉变化。
  • 是的,但是 IIRC,这会显示 both 滚动条。我真的不需要水平的。
  • 确实如此。但我无能为力帮助你:(实际上,我只认为我回复的第一句话是处理问题的真实答案。
  • 以下是更好的答案
  • @MichaelKrelin-hacker 你的回答帮我解决了问题。 tnk你。
【解决方案2】:

我不知道这是不是一篇旧帖子,但我遇到了同样的问题,如果你只想垂直滚动,你应该试试overflow-y:scroll

【讨论】:

    【解决方案3】:

    overflow-y:scroll 是正确的,但你应该将它与 html 标记一起使用,而不是正文,否则你会在 IE 7 中获得双滚动条
    所以正确的css应该是:

    html {
      overflow-y: scroll;
    }
    

    【讨论】:

    • IE 10+ 有一个浮动滚动条,所以你应该为这些浏览器禁用它
    • 这可能会导致与fancybox或twitter bootstrap modal结合使用时出现双滚动条等问题
    • 值得一提的是,它会永久显示一个垂直滚动条。可能并不总是可以接受的。
    • 我在 Chromium 和 Firefox 中都有一个双滚动条。我正在使用弹性盒;也许这是造成这种情况的原因......
    • @Garrett 试试body标签
    【解决方案4】:

    我已经解决了我的一个网站上的问题,方法是通过视口大小减去滚动条的宽度在 javascript 中显式设置正文的宽度。我使用记录在 here 的基于 jQuery 的函数来确定滚动条的宽度。

    <body id="bodyid>
    
    var bodyid = document.getElementById('bodyid');
    bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
    

    【讨论】:

    • 我什至无法解释为什么这是如此糟糕的做法。
    • @BenHooper:我想知道为什么这是不好的做法。
    • 如果调整窗口大小会发生什么?
    • 这是一个很好的解决方案。绝对不是一个坏习惯。
    • 这是一个非常不可靠的解决方案。第一个明显的错误: 1. 您可以(并且应该)使用 document.body 而不是 document.getElementById 来获取 body 元素 2. 直接设置样式被认为是一种不好的做法。检查setProperty 方法。 3. 这应该在某个监听器内部并在第一次渲染期间被调用:lang-js function handle() { document.body.style.setProperty('width', '100%'); } document.body.addEventListener('resize', handle); handle()
    【解决方案5】:

    总是显示滚动,可能不利于布局。

    尝试使用 css3 限制 body 宽度

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

    vw 是视口的宽度(请参阅this link 以获得一些解释)
    calc 在 css3 中计算
    34px 代表双滚动条宽度(请参阅 this 以获得固定或 @ 987654323@ 如果您不信任固定尺寸)

    【讨论】:

    • 除非有人需要,否则一切都是徒劳的。
    • 这在视觉上比像接受的答案所描述的那样强制使用 scollbars 在视觉上的干扰要小得多。
    • 到目前为止,这对我的需求来说效果最好,我还添加了padding-left: 34px; 以使我的页面均匀居中。
    • 这应该是公认的答案,与当前公认的不同,它实际上是在回答问题!
    • 如果您的导航栏/标题与正文背景或底部边框等颜色不同,这将导致问题。
    【解决方案6】:

    将可滚动元素的内容包装到 div 中并应用 padding-left: calc(100vw - 100%);

    <body>
        <div style="padding-left: calc(100vw - 100%);">
            Some Content that is higher than the user's screen
        </div>
    </body>
    

    诀窍在于100vw 代表 100% 的视口,包括滚动条。如果减去100%,即没有滚动条的可用空间,则最终得到滚动条的宽度,如果不存在,则得到0。在左侧创建该宽度的填充将模拟第二个滚动条,将居中的内容移回右侧。

    请注意,这仅在可滚动元素使用页面的整个宽度时才有效,但这在大多数情况下应该没有问题,因为只有少数其他情况下您具有居中的可滚动内容。

    【讨论】:

    • 通过类比内联样式更好,并且只能在these browsers 中使用,但这是一个聪明的技术——我没有意识到100vw100% 测量不同的东西,所以我从中学到了一些有用的东西!
    • 这绝对是天才,考虑到浏览器对 calc 的支持非常好,这确实是最好的答案。
    • 你可以做同样的事情,除了不是在左边添加一个边距,而是在右边添加一个负边距(参见stackoverflow.com/a/39289453/6015444)。
    • 此解决方案将导致与背景颜色类似的问题,例如答案“width: calc(100vw - 34px);”但在左侧。
    • 我建议向这种风格添加一些媒体查询-@media screen and (min-width: 800px) {...} 。在内容适合页面宽度的情况下。例如,在小分辨率上会有不必要的间隙,将内容向右移动
    【解决方案7】:

    我试图解决可能由 twitter bootstrap .modal-open 类应用于 body 引起的相同问题。解决方案html {overflow-y: scroll} 没有帮助。我发现的一种可能的解决方案是将{width: 100%; width: 100vw} 添加到html 元素中。

    【讨论】:

    • 或者改成body {overflow-y: scroll}
    • 但是,即使不需要,它也会始终显示滚动条。
    • 您应该解释一下为什么要设置两次宽度? html { width: 100vw; } 为我工作
    • 对我来说,它实际上创建了两个滚动条
    【解决方案8】:

    与接受的答案相反,该答案建议 即使内容没有溢出屏幕,浏览器窗口上的永久滚动条,我更喜欢使用:

    html{
      height:101%;
    }
    

    这是因为如果内容真的溢出,滚动条的外观会更有意义。

    Thisthis 更有意义。

    【讨论】:

    • 您的回答中至少最后一句是错误的。这与打印机打印的多余空白页类似。
    【解决方案9】:

    我使用了一些 jquery 来解决这个问题

    $('html').css({
        'overflow-y': 'hidden'
    });
    
    $(document).ready(function(){
      $(window).load(function() {
        $('html').css({
          'overflow-y': ''
        });
      });
    });
    

    【讨论】:

    【解决方案10】:
    @media screen and (min-width: 1024px){
        body {
        min-height: 700px
        }
    }
    

    【讨论】:

    • 欢迎来到 Stack Overflow!虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
    【解决方案11】:
    html {
      overflow-x: hidden;
      margin-right: calc(-1 * (100vw - 100%));
    }
    

    Example。点击“更改最小高度”按钮。

    使用calc(100vw - 100%)我们可以计算滚动条的宽度(如果不显示,则为0)。思路:使用负边距,我们可以将&lt;html&gt;的宽度增加到这个宽度。您将看到一个水平滚动条——它应该使用overflow-x: hidden 隐藏。

    【讨论】:

    • 我必须将 body 放在一个 div 中,然后将边距应用到 div 以使其工作(类似于 Rapti's answer。)但这看起来更整洁。
    • 这很好用,似乎不会在 Chrome 或 Firefox 中导致不需要的水平滚动条。为什么不直接使用calc(100% - 100vw) 而不是乘以-1
    • 这会将内容放在滚动条下,将其隐藏。
    【解决方案12】:

    我曾经遇到过这个问题,但是解决它的简单方法是这样的(这对我有用):

    关于 CSS 文件类型:

    body{overflow-y:scroll;}
    

    就这么简单! :)

    【讨论】:

      【解决方案13】:

      使用这个扩展答案:

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

      一位评论者建议添加左填充以保持居中:

      body {
          padding-left: 17px;
          width: calc(100vw - 17px);
      }
      

      但是,如果您的内容比视口宽,那么事情看起来就不正确了。要解决这个问题,您可以使用媒体查询,如下所示:

      @media screen and (min-width: 1058px) {
          body {
              padding-left: 17px;
              width: calc(100vw - 17px);
          }
      }
      

      其中 1058px = 内容宽度 + 17 * 2

      这可以让水平滚动条处理 x 溢出,并在视口足够宽以包含您的固定宽度内容时保持居中内容居中

      【讨论】:

        【解决方案14】:

        使用 calc(100vw - 100%) 发布的解决方案在正确的轨道上,但是这样做有一个问题:即使调整窗口大小,滚动条的左侧也将永远留有余量以便内容填满整个视口。

        如果您尝试使用媒体查询来解决此问题,您会遇到一个尴尬的捕捉时刻,因为当您调整窗口大小时,边距不会逐渐变小。

        这是一个解决这个问题的解决方案,AFAIK 没有缺点:

        不要使用 margin: auto 来使你的内容居中,而是使用这个:

        body {
        margin-left: calc(50vw - 500px);
        }
        

        将 500px 替换为内容最大宽度的一半(因此在本示例中,内容最大宽度为 1000 像素)。内容现在将保持居中并且边距将逐渐减小,直到内容填满视口。

        为了在视口小于最大宽度时阻止边距变为负值,只需添加如下媒体查询:

        @media screen and (max-width:1000px) {
            body {
                margin-left: 0;
            }
        }
        

        等等!

        【讨论】:

          【解决方案15】:

          如果更改大小或加载一些数据后添加滚动条,那么您可以尝试跟随,创建类并应用此类。

          .auto-scroll {
             overflow-y: overlay;
             overflow-x: overlay;
          }
          

          【讨论】:

          • 根据MDNoverflow: overlay 在 Firefox 中不受支持。 “仅在基于 WebKit(例如 Safari)和基于 Blink(例如 Chrome 或 Opera)的浏览器中受支持。”
          【解决方案16】:

          Rapti's answer 扩展,这应该也可以,但它会在body 的右侧增加更多的边距,并用负的html 边距隐藏它,而不是添加可能影响的额外填充页面的布局。这样,实际页面上没有任何变化(大多数情况下),代码仍然可以正常工作。

          html {
              margin-right: calc(100% - 100vw);
          }
          body {
              margin-right: calc(100vw - 100%);
          }
          

          【讨论】:

          • 我发现在 chrome 上,这会在我的引导站点上具有垂直滚动条的页面上添加水平滚动。
          • 您是否尝试过调查原因?检查元素检查器,看看 Bootstrap 是否与边距、滚动条或类似的东西混在一起。
          • 这可能与引导程序放置在所有内容上的 15px 边距有关,当检查页面时,容器边距位于滚动条下方。我申请了overflow-x: hidden 并修复了它。
          【解决方案17】:

          @kashesandr's solution 为我工作,但为了隐藏水平滚动条,我为正文添加了另一种样式。这是完整的解决方案:

          CSS

          <style>
          /* prevent layout shifting and hide horizontal scroll */
          html {
            width: 100vw;
          }
          body {
            overflow-x: hidden;
          }
          </style>
          

          JS

          $(function(){
              /**
               * For multiple modals.
               * Enables scrolling of 1st modal when 2nd modal is closed.
               */
              $('.modal').on('hidden.bs.modal', function (event) {
                if ($('.modal:visible').length) {
                  $('body').addClass('modal-open');
                }
              });
          });
          

          仅 JS 解决方案(当从第一个模式打开第二个模式时):

          /**
           * For multiple modals.
           * Enables scrolling of 1st modal when 2nd modal is closed.
           */
          $('.modal').on('hidden.bs.modal', function (event) {
            if ($('.modal:visible').length) {
              $('body').addClass('modal-open');
              $('body').css('padding-right', 17);
            }
          });
          

          【讨论】:

            【解决方案18】:

            如果表格的宽度不会改变,可以将包含滚动条的元素(如tbody)的宽度设置为> 100%(为滚动条留出额外的空间)并设置overflow-y为“overlay” "(以便滚动条保持固定,并且不会在表格出现时向左移动)。还要为带有滚动条的元素设置一个固定的高度,这样一旦超过高度就会出现滚动条。像这样:

            tbody {
              height: 100px;
              overflow-y: overlay;
              width: 105%
            }
            

            注意:您必须手动调整宽度 %,因为滚动条占用的空间百分比与您的表格宽度相关(即:表格宽度更小,需要更多 % 来适应滚动条,因为它的大小在像素是恒定的)

            动态表格示例:

            function addRow(tableID)
            {
                var table = document.getElementById(tableID);
                var rowCount = table.rows.length;
                var row = table.insertRow(rowCount);
                var colCount = table.rows[0].cells.length;
              
                for(var i=0; i<colCount; i++)
                {
                    var newRow = row.insertCell(i);
            
                    newRow.innerHTML = table.rows[0].cells[i].innerHTML;
                    newRow.childNodes[0].value = "";
                }
            }
             
            function deleteRow(row)
            {
                var table = document.getElementById("data");
                var rowCount = table.rows.length;
                var rowIndex = row.parentNode.parentNode.rowIndex;
            
                document.getElementById("data").deleteRow(rowIndex);
            }
            .scroll-table {
              border-collapse: collapse;
            }
            
            .scroll-table tbody {
              display:block;
              overflow-y:overlay;
              height:60px;
              width: 105%
            }
            
            .scroll-table tbody td {
              color: #333;
              padding: 10px;
              text-shadow: 1px 1px 1px #fff;
            }
            
            .scroll-table thead tr {
              display:block;
            }
            
            .scroll-table td {
                border-top: thin solid; 
                border-bottom: thin solid;
            }
            
            .scroll-table td:first-child {
                border-left: thin solid;
            }
            
            .scroll-table td:last-child {
                border-right: thin solid;
            }
            
            .scroll-table tr:first-child {
                display: none;
            }
            
            .delete_button {
                background-color: red;
                color: white;
            }
            
            .container {
              display: inline-block;
            }
            
            body {
              text-align: center;
            }
            <!DOCTYPE html>
            <html lang="en">
            <head>
              <link rel="stylesheet" href="test_table.css">
            </head>
            
            <body>
            <h1>Dynamic Table</h1>
            <div class="container">
            
              <table id="data" class="scroll-table">
                <tbody>
                  <tr>
                    <td><input type="text" /></td>
                    <td><input type="text" /></td>
                    <td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
                  </tr>
                </tbody>
              </table>
            
              <input type="button" value="Add" onclick="addRow('data')" />
            
            </div>
            
            <script src="test_table.js"></script>
            </body>
            </html>

            【讨论】:

              【解决方案19】:

              像这样简单地设置容器元素的宽度就可以了

              width: 100vw;
              

              这将使该元素忽略滚动条,它适用于背景颜色或图像。

              【讨论】:

              • 在“body”元素上设置它是可行的,但会添加一个水平滚动条(使用 Firefox)。这个解决方案不是一个好主意的任何其他原因?
              • html 上运行良好。
              • 我不得不在带有width: 100vw的html上使用:box-sizing: border-box; // so width will be calculated with paddingpadding-right: 1.2rem; // escape scroll-bar widthoverflow-x: hidden; // hide horizontal scrollbar
              【解决方案20】:

              我的方法是让轨道透明。滚动条拇指颜色为 #C1C1C1 以匹配默认滚动条拇指颜色。你可以做任何你喜欢的:)

              试试这个:

              html {
                  overflow-y: scroll;
              }
              
              body::-webkit-scrollbar {
                  width: 0.7em;
                  background-color: transparent;
              }
              
              body::-webkit-scrollbar-thumb {
                  background: #C1C1C1;
                  height:30px;
              }
              
              body::-webkit-scrollbar-track-piece
              {
                  display:none;
              }
              

              【讨论】:

                【解决方案21】:

                我尝试了溢出滚动,但它不适用于我的情况。滚动条仍然添加某种(白色)填充。有效的方法是将宽度从 100vw 更改为 100%,但对于高度,可以使用 100vh。所以这个:

                const Wrapper = styled.div`
                   min-height: 100vh
                `
                
                const Parent = styled.div`
                   width: 100%
                `
                
                const Children = styled.div`
                   width: 100%
                `
                

                编辑 我已经设置了两次宽度,因为父组件拥有一个侧边栏,而子组件。根据您的用例,您可以设置一次。

                【讨论】:

                  【解决方案22】:

                  在尝试了上述大多数在我的案例中不起作用的基于 CSS 或 JS 的解决方案之后,我只是想补充一下。 我的解决方案适用于滚动条必须在事件上消失的情况(例如,单击按钮,因为您刚刚打开了一个应该阻止页面滚动的全屏菜单)。

                  当以下样式应用于将overflow-y 变为hidden 的元素(在我的情况下是body 标签)时,这应该可以工作:

                  body {
                    overflow-x: hidden;
                    width: 100vw;
                    margin-right: calc(100vw - 100%);
                  }
                  

                  说明:body 标签的width100vw(因此它包括滚动条的宽度)。

                  通过设置margin-right,仅当您的垂直滚动条可见时才会应用边距(因此您的页面内容实际上不在滚动条下方),这意味着一旦overflow-y 发生更改,页面内容将不会重新定位。

                  注意:此解决方案仅适用于不可水平滚动的页面。

                  在 Chrome 89.0、Firefox 87.0、Safari 14.0.3 上测试

                  更新:不幸的是,它仅适用于不占用 100% 宽度的居中容器 - 否则滚动条会覆盖右侧的内容。

                  【讨论】:

                    【解决方案23】:

                    由于我在这里没有找到我的解决方案,我想添加它:

                    我不想要一个永久滚动条(已接受的解决方案),我也决定不使用负边距。他们没有(立即)在 chrome 中为我工作,我也不希望内容可能会消失在滚动条下方。

                    所以这是一个填充解决方案。

                    我的网页由三部分组成:

                    • 标题(内容左对齐)
                    • MainContent(内容居中)
                    • 页脚(内容左右对齐)

                    由于带有左侧填充的标题看起来很糟糕,并且徽标应该留在页面的角落,所以我保持它不变,因为滚动条的出现在大多数情况下不会影响它(除非窗口宽度非常小)。

                    由于 MainContent 和页脚都可以接受均匀的填充,因此我仅将以下 css 用于这两个容器:

                    .main-content, .footer {
                        /*
                         * Set the padding to the maximum scrollbar width minus the actual scrollbar width.
                         * Maximum scrollbar width is 17px according to: https://codepen.io/sambible/post/browser-scrollbar-widths 
                         */
                        padding-right: calc(17px - (100vw - 100%));
                        padding-left: 17px;
                    }
                    

                    这将使 MainContent 保持在精确的中心,并且也适用于所有宽度不超过 17 像素的滚动条。可以添加一个媒体查询,为具有覆盖滚动条的移动设备删除这些填充。 此解决方案类似于仅添加左侧填充并将宽度设置为“width: calc(100vw - 17px);”。我不能说它是否在所有情况下都表现得一样。

                    【讨论】:

                      【解决方案24】:
                      body {
                        scrollbar-gutter: stable both-edges;
                      }
                      

                      有助于滚动条重新定位的新 CSS 规范即将推出: https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter

                      【讨论】:

                        【解决方案25】:

                        总结

                        我看到了三种方式 - 每种方式都有自己的怪癖:

                        这是StackBlitz demo

                        按“切换高度”可查看内容移位。

                        滚动条装订线

                        这有limited support,但对于@support 媒体查询,我们可以使用它和overflow-y: scroll 的组合:

                        html {
                          overflow-y: scroll;
                        }
                        
                        @supports (scrollbar-gutter: stable) {
                          html {
                            overflow-y: auto;
                            scrollbar-gutter: stable;
                          }
                        }
                        
                        

                        这样,内容将永远发生变化。

                        这个解决方案的“问题”是滚动条总是有一个固定的空间。

                        溢出:覆盖 Limited support 它显然隐藏了它覆盖的任何东西。需要特别小心以确保没有隐藏任何重要内容(在缩放和文本大小更改时也是如此)。

                        可以和scrollbar-gutter结合使用:

                        html {
                          overflow-y: scroll;
                        }
                        
                        @supports (scrollbar-gutter: stable) {
                          html {
                            overflow-y: auto;
                            scrollbar-gutter: stable;
                          }
                        }
                        
                        @supports (overflow-y: overlay) {
                          html {
                            overflow-y: overlay;
                            scrollbar-gutter: auto;
                          }
                        }
                        

                        可以设置一些负边距和overflow-x: hidden,但这有在某些情况下隐藏重要内容的风险。小屏幕、自定义字体/缩放大小、浏览器扩展等。

                        计算(100vw - 100%)

                        这可以通过这样的 RTL 支持来完成:

                        html[dir='ltr'] main {
                          padding-left: calc(100vw - 100%);
                        }
                        
                        html[dir='rtl'] main {
                          padding-right: calc(100vw - 100%);
                        }
                        

                        在这种情况下,&lt;main&gt; 将是居中内容的容器。

                        只要居中的容器小于&lt;main&gt;,此处的内容就不会移动。但是一旦它达到容器的 100%,就会引入填充。查看 StackBlitz 演示并单击“切换宽度”。

                        此解决方案的“问题”是您需要媒体查询以防止“小屏幕”上的填充,即使在小屏幕上 - 当滚动条应该可见时 - 也会发生一些变化,因为没有 100% 的空间内容和滚动条。

                        结论 使用滚动条装订线可能与叠加层结合使用。如果您绝对不想要空白,请尝试使用带有媒体查询的calc 解决方案。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2012-08-16
                          • 2022-11-12
                          • 2017-09-24
                          • 2016-05-02
                          • 1970-01-01
                          • 2010-10-01
                          相关资源
                          最近更新 更多