场景

在布局时,我们经常使用 flex 来实现居中效果。例如下图场景,可能是平时比较常见的,列表中的子元素居中效果。

<style>
  .flex-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 300px;
    height: 150px;

    & > div {
      width: 100px;
      height: 80px;
    }
  }
</style>

<div class="flex-wrap">
  <div>1</div>
  <div>2</div>
</div>

flex 容器限制了宽度,且内容不够 flex 元素分配时,此时 flex 元素将会溢出容器。

使用 overflow

出现上述情况时,可能第一反应是给 flex 容器添加 overflow-y: auto 来解决。如下图,会发现 flex 容器左侧的内容仍旧无法查看。

为什么 justify-content: center; 会溢出,为什么 overflow 不是从溢出开始的地方滚动?

flex 的主轴与交叉轴

justify-content 是控制元素在容器主轴方向上的属性。如下图,设置 justify-content: center; 后,元素向主轴的中心进行排列,当 flex 容器限制宽度后,且剩余可分配空间为负数后,则两端溢出的长度相等。

css-flexbox > W3C Css3-flexbox 中文

overflow scroll origin

W3C 中,滚动的原点是矩形的锚点坐标(默认左上角,会被 direction影响)开始由 padding box 盒模型组成的矩形。且在任一轴上超出滚动原点的区域被视为负可滚动溢出区域:在此处呈现的内容对读者不可访问

Additionally, due to Web-compatibility constraints (caused by authors exploiting legacy bugs to surreptitiously hide content from visual readers but not search engines and/or speech output), UAs must clip any content in the negative scrollable overflow region (thereby behaving as if they had no scrollable overflow on the wrong side of the scroll origin).

scroll-origin

更换 direction

ltr => rtl

解决方案

safe 关键字

Chrome 115(2023/7)开始已经支持了 safeunsafe 关键字。在 W3C 中:If the size of the alignment subject overflows the alignment container, the alignment subject is instead aligned as if the alignment mode were start. 简单理解就是,当 flex 元素超出 flex 容器时,将按照 flex-start 对齐方式对齐。

溢出问题在 交叉轴 上同样存在,可参考。

.flex-wrap {
  display: flex;
  /* 同,在交叉轴(垂直方向)上居中时也可使用 safe */
  align-items: center;
  justify-content: safe center;
}

flex-item margin: auto

给首个 flex item 和 最后一个 flex item 分别添加 margin-left: automargin-right: auto

.flex-wrap {
  & > div:first-child {
    margin-left: auto;
  }
  & > div:last-of-type {
    margin-right: auto;
  }
}

添加父级,再给父级添加 overflow: auto

添加父元素,麻烦但兼容。

.flex-parent {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;

  .flex-wrap {
    display: flex;
    gap: 10px;
  }
}

参考

css-align-3
css-overflow-3
Can’t scroll to top of flex item that is overflowing container
【布局技巧】Flex 布局下居中溢出滚动截断问题