垂直滚动条导致水平滚动条

60

我的 CSS 代码如下:

div.SOMECLASS {
  position: absolute;
  max-height: 300px
  height: auto;
  width: auto;
  overflow: auto;
  ...
}
高度宽度会自动缩放。然而,高度有一个固定的最大值:一旦达到这个值,就会出现垂直滚动条。这一切都很顺利。
现在问题来了:
当垂直滚动条出现时,它会使用大约10像素的水平空间,因为滚动条将被放置在div内部。
然而,宽度并没有自动缩放以适应这些额外的10多个像素的垂直滚动条使用的空间。由于在添加垂直滚动条之前的水平宽度从width:auto设置中预期得到了正确的内容(“恰好合适”),所以div现在也显示水平滚动条 —— 以允许缺少的10像素。这很愚蠢。
  • 如何避免出现这些水平滚动条,并使div的宽度自动调整以适应垂直滚动条?
如果可能的话,我正在寻找一种解决方案,不依赖于完全禁用水平滚动,因为这可能在某些情况下是需要的(即对于某些输入)。

尝试使用overflow-y: auto。这只会在垂直方向上放置滚动条。 - Bojangles
6个回答

41

我刚想出了一个相当可行的解决方案(至少对于我遇到的这个问题而言)。

我认为 width: auto 的问题在于它的行为类似于 width: 100vw;问题在于当垂直滚动条出现时,视口宽度保持不变(尽管有大约10像素的滚动条),但是可视区域(我把它称为可见区域)会减小 10 像素。

显然,使用百分比定义宽度是基于这个“可见区域”,因此将你的代码更改为:

div.SOMECLASS {
  position: absolute;
  max-height: 300px
  height: auto;
  width: 100%;
  overflow: auto;
  ...
}

应该允许内容适当地重新缩放!

p.s. 您也可以添加overflow-x: hidden,这将阻止水平滚动条出现,而是在垂直滚动条出现时只需从您的div右侧截取约10px。


1
刚刚注意到这条信息已经两年了 - 还是希望对某些人有所帮助! - Spencer
1
将width: 100%添加到所有子div中,移除了滚动条 :) - Rusty Rob
3
这不仅解决了问题,还让我更好地理解了问题最初是如何产生的。 - J Mor
overflow: auto 让我解决了问题!谢谢! - Kelden Mayer
"width: 100vw;" 又是罪魁祸首,谢谢。 - Pking
显示剩余2条评论

21

我找到了一个可行但仍然不完美的解决方案:

我给我的div添加了一个padding-right : 15px,以自动增加整个div的大小。现在如果垂直滚动条出现,它们会适应内部填充区域,因此水平宽度仍然正常。

遗憾的是,当不需要垂直滚动时,这个填充区域也会出现,使我的div比必须要宽一点...:/然而,在我看来,这仍然比不必要的水平滚动条更可取。


8
问题在于,15像素不是跨平台通用的数字。出于辅助功能的原因,您的一些用户可能会有非常宽的滚动条。为了确保安全,不幸的是,您将不得不使用JavaScript来查找滚动条的宽度。 - Michael Scheper
1
你说得对... 这个问题确实概括了互联网的所有问题。 :/ - fgysin
无论如何,使用CSS3可以实现。也许CSS4会有更多的方法来访问系统数据,除了在CSS2中引入的系统颜色。 - Michael Scheper
@Michael:你知道有什么Javascript(或jQuery)技巧可以用来找出是否有滚动条以及它有多宽,以便适当地调整div的宽度吗? - OsakaWebbie
@OsakaWebbie:我已经有一段时间没有这样做了,但对我有效的基本上与这些页面描述的相同:http://chris-spittles.co.uk/jquery-calculate-scrollbar-width/ https://dev59.com/ynNA5IYBdhLWcg3wX8rk - Michael Scheper

4
经常使用100vw是问题所在。只需将其移除,您的宽度就会变为100%,这正是您想要的。

0

我曾遇到同样的问题,并通过以下设置CSS进行了修复:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    height: 100%;
}

body {
    min-height: 100%;
    width: 100%;
}

这里还有一个很棒的视频,非常清晰地解释了它,或者可以看原始文章


0

这个错误(仅限于Firefox)即使不设置固定宽度也会发生。

例如,如果您在一个可垂直滚动的容器div(overflow: auto;)内部放置一个灵活的包装div(display: inline-block;),那么当您调整窗口大小小于内容可以换行时,首先,水平滚动条将出现在您的容器div中,只有在此之后,灵活的包装div才会增长或最终在您的窗口中出现第二个水平滚动条。

结果是一个无用的水平滚动条,只能滚动垂直滚动条的宽度:

Screenshot of the example code showing the problem and a solution

为了解决这个问题,您可以使用此示例中的JavaScript代码(在Firefox和Chromium中进行了测试):
<!DOCTYPE html>
<html>
<body>
    <style type="text/css">
    .page {height: 200px;width: 400px;overflow: auto;background-color: #ccc;border: 5px solid #000;margin: 5px;}
    .wrapper {display: inline-block;min-width: 100%;margin: 20px;}
    .scroller {overflow: auto;max-height: 100px;background-color: #f00;}
    .content {min-height: 500px;min-width: 400px;background-color: #cfc;}
    </style>
    <div class="page">
        <div class="wrapper">
            <div class="scroller">
                <div class="content">
                    The wrapper-div should expand to fit the scroller content.
                    Reduce the browser window width, and a useless horizontal scrollbar appears.
                </div>
            </div>
        </div>
    </div>
    <div class="page">
        <div class="wrapper">
            <div class="scroller ensure-scrollbar-width-padding">
                <div class="content">
                    But with the javascript-function, this is now fixed.
                    There is no horizontal scrollbar in the wrapper-div.
                </div>
            </div>
        </div>
    </div>
    <script>
    var ensureScrollbarWidthPadding = function(elem)
    {
        if(!parseInt(elem.scrollWidth) || !parseInt(elem.clientWidth) || !parseInt(elem.offsetWidth))
        {
            return; // no browser-support for this trick
        }

        var update = function()
        {
            // reset to as if not having any right-padding
            elem.style.paddingRight = '0px';

            // check if horizontal scrollbar appeared only because of the vertical scrollbar
            if(elem.scrollWidth !== elem.clientWidth)
            {
                elem.style.paddingRight = (elem.offsetWidth - elem.clientWidth) + 'px';
            }
            else
            {
                elem.style.paddingRight = '0px';
            }
        };

        window.addEventListener('resize', update, false);
        window.addEventListener('load', update, false);

        update();

        return update;
    };

    (function()
    {
        var elems = document.getElementsByClassName('ensure-scrollbar-width-padding');
        for(var i=0;i<elems.length;++i)
        {
            ensureScrollbarWidthPadding(elems[i]);
        }
    })();
    </script>
</body>
</html>

javascript函数ensureScrollbarWidthPadding会动态地向垂直可滚动的容器添加一个padding-right,以确保水平滚动条永远不会出现。

是的。这是Firefox的一个bug。在我的情况下,当我在包含表格的容器div中使用overflow: auto,并且该表格具有white-space: nowrap;列时,它会被触发。我有多个带有此设置的表格,但只有一些会出现破坏布局的水平滚动条。因此,对于我来说,padding-right解决方案行不通。 - insaner

0

我的问题在谷歌上排名第一(与 OP 类似,但不完全相同)。

以下是一个看似不必要的水平滚动条的常见情况:

您有一个元素,比如一个表格,它使用自动调整大小。如果自动调整大小是在添加所有行之前完成的,则不会为垂直滚动条计算足够的空间。在添加行之后进行调整大小可以解决我的问题 - 即使在这种情况下,我仍然需要一个超时。

this.http.get('someEndPoint').subscribe(rows => {
  this.rowData = rows;
  setTimeout(()=>{sizeColumnsToFit()}, 50);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接