阅读 90

CSS中的溢出问题

如果你是一个前端开发者,你可能遇到过水平滚动条问题,尤其是在移动端。因为造成滚动条问题的原因有很多,所以没有直接的解决方案。有些问题可以很快解决,有些则需要一点调试技巧。

什么是溢出问题?

在讨论溢出问题之前,我们应该弄清楚什么是溢出问题。当网页上无意中出现一个水平滚动条,允许用户水平滚动时,就会发生溢出问题。它可以由不同的因素引起。

它的发生可能是因为内容出乎意料的宽,或者固定宽度的元素比视口宽。我们将在本文中探讨所有的原因。

如何发现溢出

解决这个问题的一个重要部分是首先注意到它。如果我们知道它发生的时间和地点,我们就可以对网页的那个部分进行监控。有不同的方法来检测溢出,包括手动向左或向右滚动或使用JavaScript。

让我们来探讨一下检测溢出的方法。

向左或向右滚动

发现溢出问题的第一个方法是水平滚动页面。如果你能够滚动,这就是一个警告,说明页面有问题。

使用JavaScript查找比正文更宽的元素

我们可以在浏览器控制台中添加一个片段,以显示任何比正文更宽的元素。这对于有很多元素的页面来说是很方便的。

var docWidth = document.documentElement.offsetWidth;

[].forEach.call(
  document.querySelectorAll('*'),
  function(el) {
    if (el.offsetWidth > docWidth) {
      console.log(el);
    }
  }
);
复制代码

CSS轮廓的拯救

对页面上的所有元素应用CSS的outline ,可以给我们提示超出页面的元素body

* {
    outline: solid 1px red;
}
复制代码

更妙的是,Addy Osmani有一个脚本,可以为页面上的每个元素添加一个随机颜色的轮廓。

[].forEach.call($$(""),function(a){a.style.outline="1px solid #"+(~~(Math.random()(1<<24))).toString(16)})
复制代码

Firefox中的溢出标签

Firefox有一个有用的功能,可以告诉你哪些元素会导致溢出。希望其他浏览器也能增加这个功能!

删除页面元素

另一个常见的方法是打开浏览器的DevTools,开始一个一个地删除元素。一旦问题消失,那么你刚刚删除的部分可能就是原因所在。我发现这个方法在你已经发现问题但不知道为什么会发生的情况下很有用。

一旦你找到了溢出发生的位置,那么为进一步的调试制作一个缩小的测试案例就会更容易。

常见的溢出问题

固定宽度的元素

溢出的最常见原因之一是固定宽度的元素。一般来说,不要固定任何元素的宽度,这些元素应该在多个视口尺寸下工作。

.element {
    /* Don’t do this */
    width: 400px;
}
复制代码

使用没有包裹的Flexbox

尽管Flexbox很有用,但在没有可用空间的情况下,不允许项目包裹到新的一行是有风险的。

.parent {
    display: flex;
}
复制代码

在这里,灵活的项目可能会导致水平溢出,以防空间不足以将它们全部放在一行中。

当灵活的父项应该在不同的视口尺寸下工作时,请确保使用flex-wrap: wrap

.parent {
    display: flex;
    /* Do this */
    flex-wrap: wrap;
}
复制代码

CSS网格

当你使用CSS网格时,响应式设计很重要。以下面这个网格为例。

.wrapper {
    display: grid;
    grid-template-columns: 1fr 300px 1fr;
    grid-gap: 1rem;
}
复制代码

上面的例子很好用,除非视口窄于300像素。如果是这样的话,就会发生溢出。

为了避免这样的问题,只有在有足够空间的情况下才使用网格。我们可以像这样使用一个CSS媒体查询。

.wrapper {
    display: grid;
    grid-template-columns: 1fr;
    grid-gap: 1rem;
}

@media (min-width: 400px) {
    .wrapper {
        grid-template-columns: 1fr 300px 1fr;
    }
}
复制代码

长字型

溢出的另一个常见原因是一个长字不适合在视口中出现。由于视口的宽度,这种情况在移动端发生得更多。

为了解决这个问题,我们需要使用overflow-wrap 属性。

.article-content p {
  overflow-wrap: break-word;
}
复制代码

我写过一篇关于用CSS处理长短内容的详细文章。

这种修复方法对于用户生成的内容特别有用。一个完美的例子是一个评论线程。一个用户可能会在他们的评论中粘贴一个长的URL,这应该用overflow-wrap 属性来处理。

CSS Flexbox中的最小内容尺寸

另一个有趣的溢出原因是Flexbox中的最小内容尺寸。这是什么意思?

根据该规范

"默认情况下,Flex项目不会缩减到低于其最小内容尺寸(最长的单词或固定尺寸元素的长度)。要改变这一点,请设置min-widthmin-height 属性。"

这意味着,一个有长字的柔性项目不会收缩到其最小内容尺寸以下。

为了解决这个问题,我们可以使用overflow ,而不是visible ,或者我们可以在flex item上设置min-width: 0

.card__name {
    min-width: 0;
    overflow-wrap: break-word;
}
复制代码

CSS网格中的最小内容尺寸

与Flexbox一样,我们在CSS Grid中也有同样的最小内容尺寸的概念。但是,解决方案有些不同。CSS-Tricks将其称为 "网格吹出"。

让我们来探讨一下这个问题。假设我们有一个带有旁白和主要部分的包装,用CSS网格布置。

.wrapper {
    display: grid;
    grid-template-columns: 248px 1fr;
    grid-gap: 40px;
}
复制代码

另外,我们在主部分有一个滚动的部分,为此我使用了flexbox。

.section {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
}
复制代码

请注意,我没有添加flex-wrap ,因为我希望flex项目在同一行。然而,这并不奏效,它造成了水平溢出。

为了解决这个问题,我们需要使用minmax() ,而不是1fr 。这样一来,主元素的最小内容尺寸就不会是auto

.wrapper {
  display: grid;
  grid-template-columns: 248px minmax(0, 1fr);
  grid-gap: 40px;
}
复制代码

负的边距

一个元素被放置在屏幕之外会导致溢出。通常情况下,这是因为该元素有一个负的边距。

在下面的例子中,我们有一个负边距的元素,而文档的语言是英语(即从左到右)。

.element {
    position: absolute;
    right: -100px;
}
复制代码

有趣的是,当该元素被定位在另一侧时,没有溢出。这是为什么呢?

我最近遇到了这个问题,并写了相关的文章。事实证明,这种行为是故意的。根据CSS规范

"UA必须在盒子的块开始和内联开始的一侧剪辑滚动容器的可滚动溢出区域(从而表现为在该侧没有可滚动溢出)"。

对于一个英文文档来说,inline-start边是左边,所以任何在左边屏幕外定位的元素都会被剪掉,因此不会有溢出。

如果真的需要将一个元素定位到屏幕外,请确保将overflow: hidden ,以避免任何溢出。

没有图像max-width

如果你不提前处理大型图片,你会看到溢出。请确保在所有图片上设置max-width: 100%

img {
    max-width: 100%;
}
复制代码

视口单位

使用100vw 确实有一个缺点,那就是当滚动条可见时,它可能导致溢出。在macOS上,100vw 是好的,不会导致水平滚动。

在Windows上,滚动条默认总是可见的,所以会发生溢出。

其原因是,在数值为100vw ,没有意识到浏览器的垂直滚动条的宽度。因此,width 将等于100vw 加上滚动条的宽度。不幸的是,没有CSS可以解决这个问题。

然而,我们可以使用JavaScript来测量视口的宽度,不包括滚动条。

function handleFullWidthSizing() {
  const scrollbarWidth = window.innerWidth - document.body.clientWidth

  document.querySelector('myElement').style.width = calc(100vw - ${scrollbarWidth}px)
}
复制代码

注入的广告

在页面加载时注入的广告如果比其父元素宽,会导致溢出。在父元素上添加overflow-x: hidden ,以防止这种情况。

仔细检查网站上的每个广告,以确保它不会导致溢出。

overflow-x: hidden 适用于body 是个好主意吗?

选择overflow-x: hidden ,就像贴上绷带,而不解决这个问题。如果你有溢出,那么最好是解决根本问题。

此外,将overflow-x: hidden 应用于body 元素也不是一个好主意,因为如果父元素有overflow-x: hidden ,那么position: sticky 就不会起作用。

如何避免CSS中的溢出

以下是减少CSS中溢出问题需要检查的事项。我希望你能发现它的作用

用真实的内容进行测试

没有什么比用网站上的真实内容进行测试更重要的了。这样做,你可以确保布局可以处理不同种类的内容。

考虑到用户生成的内容

对于像评论线程这样的组件,要考虑到用户会粘贴一个长的URL或输入一个长的单词,如上所述。

谨慎地使用CSS网格和Flexbox

尽管CSS网格和Flexbox很有用,但如果使用不当,它们很容易造成溢出。正如我们所讨论的,不使用flex-wrap: wrap ,就会导致溢出,当屏幕窄于350像素时,grid-template-columns: 1fr 350px

在SmashingMag上进一步阅读。

文章分类
前端
文章标签