提问者:小点点

无法滚动到溢出容器的flex项的顶部


因此,在尝试使用flexbox创建一个有用的模式时,我发现了一个似乎是浏览器的问题,我想知道是否有已知的修复或变通方法--或者如何解决它的想法。

我想解决的问题有两个方面。 首先,使模态窗口垂直居中,这是预期的工作方式。 第二个是让模式窗口滚动--向外部滚动,这样整个模式窗口就滚动了,而不是滚动其中的内容(这样您就可以拥有下拉列表和其他UI元素,这些元素可以扩展到模式的边界之外--比如自定义日期选择器,等等)

然而,当将垂直居中与滚动条结合时,模式的顶部可能会变得无法访问,因为它开始溢出。 在上面的例子中,您可以调整大小以强制溢出,这样做时它允许您滚动到模式的底部,但不能滚动到顶部(第一段被切断)。

下面是示例代码的链接(高度简化)

https://jsfiddle.net/dh9k18k0/2/

.modal-container {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-x: auto;
}
.modal-container .modal-window {
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  // Optional support to confirm scroll behavior makes sense in IE10
  //-ms-flex-direction: column;
  //-ms-flex-align: center;
  //-ms-flex-pack: center;
  height: 100%;
}
.modal-container .modal-window .modal-content {
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  width: 100%;
  max-width: 500px;
  padding: 10px
}

这影响(当前)火狐,Safari,Chrome和Opera。 有趣的是,如果您在IE10供应商前缀的css中进行评论,它在IE10中的行为是正确的--我还没有费心在IE11中进行测试,但假设它的行为与IE10的行为相匹配。

任何想法都是好主意。 指向已知问题的链接,或此行为背后的推理也将是有用的。


共3个答案

匿名用户

Flexbox使对中变得非常容易。

通过简单地将align-items:centerjustify-content:center应用到flex容器,您的flex项将垂直和水平居中。

但是,当flex项大于flex容器时,这种方法会出现问题。

正如问题中所指出的,当flex项目溢出容器时,容器顶部将变得不可访问。

对于水平溢出,左部分变得不可访问(或右部分,在RTL语言中)。

下面是一个LTR容器的示例,该容器具有justify-content:center和三个flex项:

有关此行为的解释,请参见本答案的底部。

若要解决此问题,请使用flexbox自动边距,而不是justify-content

使用自动边距,溢出的flex项可以垂直和水平居中,而不会失去对其任何部分的访问。

所以代替flex容器上的这段代码:

#flex-container {
    align-items: center;
    justify-content: center;
}

在flex项上使用以下代码:

.flex-item {
    margin: auto;
}

修订演示

safe值添加到关键字对齐规则中,如下所示:

justify-content: safe center

align-self: safe center

来自CSS框对齐模块规范:

4.4. 溢出对齐:safeunsafe关键字和滚动安全限制

当“flex项目”大于“flex容器”时,它会溢出。 在这种情况下,如果采用某些对齐模式,可能会导致数据丢失:例如,如果侧边栏的内容居中,当它们溢出时,可能会将它们的部分框发送到视口的起始边缘,从而无法滚动到该边缘。

要控制这种情况,可以显式指定溢出对齐模式。 unsafe对齐在溢出情况下遵守指定的对齐模式,即使它会导致数据丢失,而safe对齐在溢出情况下更改对齐模式,以试图避免数据丢失。

默认的行为是将对齐主题包含在可滚动区域中,尽管在编写本文时还没有实现这个安全特性。

安全

如果[flex item]的大小溢出[flex container],则[flex item]将改为对齐,就像对齐模式是[Flex-Start]一样。

不安全

无论[flex item]和[flex container]的相对大小如何,给定的对齐值都是有效的。

注意:Box Alignment模块适用于多个Box布局模型,而不仅仅是Flex。 所以在上面的spec摘录中,括号中的术语实际上是说“对齐主题”,“对齐容器”和“开始”。 我使用了特定于Flex的术语来保持对这个特定问题的关注。

弹性项目注意事项

与CSS中的其他对中方法不同,FlexBox的对齐属性执行“true”居中。 这意味着flex项将保持居中,即使它们溢出了flex容器。

然而,如果它们溢出页面的上边缘或左边缘[...],这有时会有问题,因为即使那里有内容,您也无法滚动到该区域!

在未来的版本中,对齐属性将被扩展为具有“安全”选项。

现在,如果这是一个问题,您可以使用边距来实现居中,因为边距会以一种“安全”的方式做出响应,如果溢出,就会停止居中。

不使用align-属性,只需将auto页边距放在要居中的flex项上。

不要使用justify-属性,而是将自动边距放置在flex容器中第一个和最后一个flex项的外部边缘上。

自动边距将“弹性”并假定剩余空间,当有剩余空间时将弹性项居中,当没有剩余空间时切换到正常对齐。

但是,如果您试图在多行flexbox中用基于边距的居中位置替换justify-content,那么您可能就不走运了,因为您需要在每行的第一个和最后一个flex项目上放置边距。 除非您能够提前预测哪些项目将结束在哪一行上,否则您无法可靠地使用主轴中基于边距的居中来替换justify-content属性。

匿名用户

好吧,正如墨菲定律所说的,我在贴出这个问题之后的阅读,得到了一些结果--虽然没有完全解决,但还是有点用处。

在发布之前,我对min-height进行了一些尝试,但是没有意识到内部的大小约束,这对于规范来说是相当新的。

http://caniuse.com/#feate=intrinsic-width

在flexbox区域添加min-height:min-content确实解决了Chrome中的问题,使用供应商前缀也修复了Opera和Safari,不过Firefox仍然没有解决。

min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome

还在寻找Firefox上的想法,以及其他潜在的解决方案。

匿名用户

我只用了3个容器就搞定了。 诀窍是将flexbox容器与控制滚动的容器分开。 最后,将所有内容放入根容器中,使其居中。 以下是营造效果的基本风格:

CSS:

.root {
  display: flex;
  justify-content: center;
  align-items: center;
}

.scroll-container {
  margin: auto;
  max-height: 100%;
  overflow: auto;
}

.flex-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

HTML:

<div class="root">
  <div class="scroll-container">
    <div class="flex-container">
      <p>Lorem ipsum dolor sit amet.</p>
    </div>
  </div>
</div>

我在这里创建了一个演示:https://jsfiddle.net/r5jxtgba/14/