371

因此,在尝试使用 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
}

这会影响(当前)Firefox、Safari、Chrome 和 Opera。如果您在 IE10 供应商前缀 css 中评论,它在 IE10 中的行为确实很有趣——我还没有在 IE11 中进行测试,但假设行为与 IE10 的行为匹配.

任何想法都会很好。指向已知问题的链接或此行为背后的推理也会很有用。

4

8 回答 8

707

问题

Flexbox 使居中变得非常容易。

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

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

如问题中所述,当弹性项目溢出容器时,顶部变得不可访问。

在此处输入图像描述

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

这是一个具有justify-content: center三个弹性项目的 LTR 容器的示例:

在此处输入图像描述

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


解决方案#1

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

使用auto边距,溢出的弹性项目可以垂直和水平居中,而不会失去对其任何部分的访问权限。

因此,不要在 flex 容器上使用此代码:

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

在弹性项目上使用此代码:

.flex-item {
    margin: auto;
}

在此处输入图像描述

修改后的演示


解决方案 #2(尚未在大多数浏览器中实现)

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

justify-content: safe center

或者

align-self: safe center

来自CSS 框对齐模块规范

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

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

为了控制这种情况,可以明确指定溢出对齐模式。Unsafe对齐在溢出情况下遵循指定的对齐模式,即使它导致数据丢失,而safe对齐在溢出情况下更改对齐模式以避免数据丢失。

默认行为是将对齐主题包含在可滚动区域内,尽管在编写此安全功能时尚未实现。

safe

如果 [flex item] 的大小超出了 [flex container],则 [flex item] 会像对齐模式是 [ flex-start] 一样对齐。

unsafe

无论 [flex item] 和 [flex container] 的相对大小如何,都会遵循给定的对齐值。

注意:Box Alignment Module 可用于多个盒子布局模型,而不仅仅是 flex。因此,在上面的规范摘录中,括号中的术语实际上是“对齐主题”、“对齐容器”和“ start”。我使用了特定于 flex 的术语来专注于这个特定的问题。


MDN 对滚动限制的解释:

弹性项目注意事项

与 CSS 中的其他居中方法不同,Flexbox 的对齐属性会“真正”居中。这意味着弹性项目将保持居中,即使它们溢出弹性容器。

但是,如果它们溢出页面的顶部边缘或左​​侧边缘 [...],有时这可能会出现问题,因为您无法滚动到该区域,即使那里有内容!

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

现在,如果这是一个问题,您可以改为使用边距来实现居中,因为它们将以“安全”的方式响应并在溢出时停止居中。

而不是使用align-属性,只需auto在您希望居中的弹性项目上放置边距。

代替justify-属性,将自动边距放在弹性容器中第一个和最后一个弹性项目的外边缘。

边距将auto“伸缩”并占据剩余空间,当有剩余空间时将弹性项目居中,当没有剩余空间时切换到正常对齐。

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

于 2015-10-31T18:51:53.277 回答
26

好吧,正如墨菲定律所说,我在发布这个问题后所做的阅读导致了一些结果 - 没有完全解决,但仍然有些有用。

在发布之前我玩了一下 min-height ,但没有意识到规范中相当新的内在尺寸限制。

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

将 a 添加min-height: min-content到 flexbox 区域确实解决了 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 和其他潜在解决方案的想法。

于 2015-10-31T17:51:08.730 回答
21

我只用了 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/

于 2017-12-11T19:53:12.233 回答
3

我想我找到了解决办法。它适用于大量文本少量文本。你不需要指定任何东西的宽度,它应该在 IE8 中工作。

.wrap1 {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-y: auto;
}
.wrap2 {
  display: table;
  width: 100%;
  height: 100%;
  text-align: center;
}
.wrap3 {
  vertical-align: middle;
  display: table-cell;
}
.wrap4 {
  margin: 10px;
}
.dialog {
  text-align: left;
  background-color: white;
  padding: 5px;
  border-radius: 3px;
  margin: auto;
  display: inline-block;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
  <div class="wrap2">
    <div class="wrap3">
      <div class="wrap4">
        <div class="dialog">
          <p>Lorem ipsum dolor sit amet.</p>
        </div>
      </div>
    </div>
  </div>
</div>

于 2016-09-15T23:04:07.777 回答
1

根据 MDN,safe现在可以将值提供给 和 之类的align-items属性justify-content。描述如下:

如果项目的大小溢出对齐容器,则项目将按照对齐模式进行对齐start

因此,它可以按如下方式使用。

.rule
{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: safe center;
}

但是,尚不清楚它有多少浏览器支持,我找不到任何使用示例,而且我自己也遇到了一些问题。在这里提及它以引起更多关注。

于 2017-12-04T13:52:09.527 回答
1

您可能应该使用该margin: auto技术,但是如果您出于某种原因不想使用 flexbox,则可以使用带有垂直对齐技巧的伪元素来完成此操作。

例子

如果 codepen 不起作用

<div class="wrapper">
  <div class="modal"></div>
</div>

<style>
.wrapper {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #000;
  overflow-y: auto;
  text-align: center;
}

/* Required for centering */
.wrapper:before {
  content: '';
  height: 100%;
  width: 0;
  vertical-align: middle;
  display: inline-block;
}

.modal {
  /* Required for centering */
  display: inline-block;
  vertical-align: middle;


  text-align: left;
  width: 320px;
  height: 320px;
  background-color: #fff;
  border-radius: 25px;
}
</style>

它通过创建一个内联元素来工作,该元素作为父元素的完整高度并显示为内联块,就像您的目标元素( .modal )一样,然后vertical-align: middle在两者上使用,并且浏览器发挥了它的魔力 - 它对齐.modal 和伪元素,就好像它们是常规文本一样。您还可以在模态 div 上使用顶部/底部垂直对齐。结合text-align,modal可以放在任意位置。

您可以text-align: center在父级上使用将对话框水平居中。任何浏览器都应该支持并且溢出也有效。

在撰写本文时(2021 年 9 月 15 日),以隐身模式访问 Google 会显示一个 cookie 策略模式,该模式使用此技术进行居中。

于 2021-09-15T17:34:43.897 回答
0

2 Container Flex Method with Table fallback 测试 IE8-9,flex 在 IE10,11 中工作。编辑:编辑以确保在内容最少时垂直居中,添加了旧版支持。

正如迈克尔回答的那样,问题源于高度从视口大小继承而来,导致孩子溢出。https://stackoverflow.com/a/33455342/3500688

一些更简单的东西,并使用 flex 来维护弹出容器(内容)内的布局:

#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
    /* display: flex; */
    /* flex-wrap: wrap; */
}
		<!--[if lt IE 10]>
<style>
	  #popup {
			display: table;
			width:100%;
		}
		.iewrapper {
			display: table-cell;
			vertical-align: middle;
		}
	</style>
	<![endif]-->
<div id="popup">
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
    <div class="container">
        <p class="p3">Test</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    </div>
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>

于 2019-03-16T22:45:36.280 回答
0

我还设法使用额外的容器来做到这一点

HTML

<div class="modal-container">
  <div class="modal">
    <div class="content-container">
       <div class="content">
         <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>
      </div>
  </div>  
</div>

CSS

.modal-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: black;
}

.modal {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #aaa;
  height: 80%;
  width: 90%;
}

.content-container {
  background-color: blue;
  max-height: 100%;
  overflow: auto;
  padding:0;
}

.content {
  display: flex;
  background-color: red;
  padding: 5px;
  width: 900px;
  height: 300px;
}

在 jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/

更改.content宽度/高度值并查看

于 2018-10-04T08:38:44.960 回答