【问题标题】:Prevent a centered layout from shifting its position when scrollbar appears防止出现滚动条时居中布局移动其位置
【发布时间】:2012-03-09 15:11:19
【问题描述】:

我的页面布局看起来像something like this:

<style type="text/css">
#content-wrap
{
    margin: 0 auto;
    width: 800px;
}
</style>

<div id="content-wrap">
</div>

您会注意到,当垂直滚动条出现时,content-wrap div 会稍微改变其位置。一种情况是当浏览器开始逐步渲染页面而不显示垂直滚动条时,然后确定需要滚动条,因为内容高于“折叠”。这会将 div 向左移动大约 10px。

在不强制浏览器始终显示滚动条的情况下解决此问题的最佳方法是什么?

【问题讨论】:

  • 内容居中为什么需要水平滚动条?
  • 没有水平滚动条,你是说垂直滚动条吗?
  • 是的,垂直滚动条,谢谢指正。
  • 当滚动条出现时,您的浏览器宽度变小,即使在大型网站上也会发生。您可以将min-height: 属性设置为足够大以始终显示滚动条
  • 解决这个问题的最好方法是强制浏览器总是显示垂直滚动条。 您为什么不想这样做? html { overflow-y: scroll; } 这样做没有任何缺点,除了一些小的 edge cases

标签: html css scroll


【解决方案1】:

恐怕解决此问题的最佳方法是使用html {overflow-y: scroll;} 强制滚动条始终可见。您遇到的问题是,当滚动条出现时,“可用区域”会缩小 10 像素。这会导致计算出的左侧边距缩小滚动条宽度的一半,从而将居中的内容稍微向左移动。

一个可能的解决方案可能是使用 JavaScript 计算边距,而不是使用 margin: 0 auto; 并以某种方式补偿滚动条出现时“丢失”的像素,但我担心它会很混乱,内容可能会移动在您计算和应用新边距时无论如何都会有一点点。

【讨论】:

  • Overflow-y:scroll 无疑是​​当今最好的方法。当/如果其他操作系统复制 Apple 的 iOS 风格的浮动滚动条,这个问题将不复存在。
【解决方案2】:

如果您的网站是“响应式”(对宽度有反应):

第 1 步:width: 100vw 添加到包装器元素。这使它与视口一样宽,忽略滚动条的外观。

第 2 步:overflow-x: hidden 添加到内容元素。这将删除水平滚动条(在垂直滚动条出现时创建,以允许用户“查看”它)。

“包装元素”在我们的例子中是指另一个 div 围绕你的#content-wrap

也适用于您的案例,经过测试:

<style type="text/css">
body {
    overflow-x: hidden;
}
#wrap-wrap {
    width: 100vw;
}
#content-wrap
{
    margin: 0 auto;
    width: 800px;
}
</style>
<div id="wrap-wrap">
    <div id="content-wrap">
    </div>
</div>

确保页面上没有任何有用的内容足够宽以被滚动条捕获。

比如可以保证内容元素的(水平内边距+边框+水平外边距)之和比滚动条宽)。


如果您的网站是固定宽度 + 居中(您的情况):

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

这将在滚动条出现时为其添加宽度相等的左边距。没有时为 0。取自 here,但经过测试。

【讨论】:

    【解决方案3】:

    你必须使用:

    html {
      overflow-y: overlay;
    }
    

    仅 WebKit (Safari) 或 Blink (Chrome, Opera) 支持

    【讨论】:

    • 这是新事物吗?
    • 仅 WebKit (Safari) 或 Blink (Chrome, Opera) 支持
    【解决方案4】:

    使用 jquery 并将其放在标签的开头:

    <script type="text/javascript">
    function checkheight(){
     if ($(document).height() > $(window).height()) {
     //that is if there is vertical scrollbar
     document.getElementById('yourcenteredcontainer').style.paddingLeft='8px'; 
     //8px because the scrollbars are (?always?) 16px
     }else{
     document.getElementById('yourcenteredcontainer').style.paddingLeft='0px';
     }
    }
    </script>
    

    并调用函数 checkheight(); 在标签的末尾加上,无论您有 onclick(或其他)事件,使页面的高度变长或变短。

    【讨论】:

    • 这确实有效。但是在 firefox(33) 中使用 7px,在 Chrome(38) 中使用 8px
    【解决方案5】:

    如果你会使用Javascript,你可以将content-wrap的宽度设置为窗口的内部宽度减去滚动条的标准宽度。

    你会遇到一些问题。

    • 用户必须启用 Javascript
    • 您不知道垂直滚动条的宽度是多少,尤其是在没有滚动条的情况下!所以你将不得不猜测。 20 像素似乎是个不错的猜测。
    • 不同的浏览器有不同的方式告诉你想要窗口的内部宽度。

    所以如果你能忍受所有这些,你可以做这样的事情(在伪代码中)

    if window.innerWidth is defined :
       set the width of the div to window.innerWidth-20px
    else if we're running on Internet Explorer :
       set the width to document.documentElement.offsetWidth-20px
    otherwise :
       we're out of luck and we best leave the width as is.
    

    【讨论】:

      【解决方案6】:

      首先,我建议优化 HTML,以便加载/渲染不会花费很长时间。如果加载/渲染速度很快,滚动条就不会出现“为时已晚”。加载/渲染需要很长时间?检查 chrome 调试工具 (F12) 中的网络选项卡。在 Chrome 调试工具中进行审核。

      有多种因素可以使文档变为“reflow”,并且即使浏览器从一开始就知道必要的测量值,也会出现滚动条。您是否使用表格进行布局 - 不要!他们可能需要多次渲染。你有没有指定宽度/高度的图像吗?然后在每个图像加载时都需要重新渲染文档。指定&lt;img ... style="width: ..px; height: ..px"&gt;。是CSS sane and efficient

      如果您无法降低加载/渲染速度,我认为最好的办法是在启用 javascript 的情况下不使用浏览器的滚动条。这样您就可以控制它并将其放置在绝对位置,这样就不会影响水平定位。

      让您的滑块以display: none 开头。监视 dom 就绪事件以及图像加载事件以及窗口调整大小事件。加载页面后,加载图像并且调整窗口大小时每次都运行相同的功能。它将确定是否需要滚动条并显示或隐藏它。

      例如,您可以使用JQuery UI Slider 并将其maxValue 设置为$(document).height() - $(window).height(),监视滑块更改事件,然后将正文滚动到滑块的值等等。

      如果禁用了 javascript,则回退将是常规滚动条,那么您就无法对轻微的水平移动进行任何操作。

      但实际上我认为水平移位的问题太小了,无法花时间修复自定义滚动条,并检查它是否在所有平台上都运行良好等。首先进行 HTML/CSS 优化。

      【讨论】:

        【解决方案7】:

        你可以试试这个解决方案:https://stackoverflow.com/a/67213174/14302216

        但宽度不能是相对的。可能, width:100vw 将适用于父级,但我不确定您将如何设置子级宽度。恐怕 calc(100vw-16px) 不起作用。但是如果你可以为孩子设置像 widht:800px 这样就可以了!

        【讨论】:

          猜你喜欢
          • 2014-02-17
          • 2019-08-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多