Firefox:flexbox 容器内的项目不保持纵横比

Firefox: Item inside flexbox container does not preserve aspect ratio

我在解决时遇到了这个问题。
我有以下基本布局:

+-----+-----------------+
|     |                 |
|  c  |c   +------+     |
|  o  |o   | item |     |
|  l  |l   |      |     |
|     |    +------+     |
|  1  |2                |
+-----------------------+

col 1col 2 是通过 CSS 网格创建的。现在,我正在努力将 item(水平和垂直)居中 col 2.

#content {
  display: grid;
  grid-template-columns: minmax(13rem, 15%) minmax(85%, 100%);
  
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#circle {
  background: #7FFF00;
  
  width: 9%;
  padding-top: 9%;
  border-radius: 50%;
  
  margin: auto;
}

.menu {
  background: #D2691E;
  
  grid-row-start: 1;
  grid-row-end: 1;
}

.circle-area {
  background: #191970;
  
  grid-row-start: 1;
  grid-row-end: 1;
  grid-column-start: auto;
  grid-column-end: span 2;
  
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
<body>
<div id='content'>
<div class='menu'></div>
<div class='circle-area'>
<div id='circle'></div>
</div>
</div>
</body>

Code above on JSFiddle

在 Chrome 62.0 和 Safari 11.0 中测试时,我的代码按预期工作(item 保存它的纵横比并垂直和水平居中)。尽管当我使用 Firefox (56.0) 时 - 纵横比在 window 调整大小时发生了变化。我已经尝试了另一个 centering technique - using grid (JSFiddle) (结果是相同的 Firefox 不会保留纵横比)。

现在,commenting out (JSFiddle) 来自 css 的 flex 部分将使 Firefox 保持宽高比,尽管项目不再垂直居中。

我的问题是:

  1. 这是 Firefox 中的已知问题(错误),还是我的代码有问题?
  2. 什么是 fix/workaround 在 col 2 内垂直和水平居中 item,同时保持纵横比(最好使用 flex )?

基于百分比的垂直浏览器行为 margins/paddings 简而言之

不是一个错误本身,但可能是由于浏览器的不同实现如何基于百分比的垂直间距(顶部和底部) margins/paddings) 应在 flex or grid 布局上下文中计算:

Percentage margins and paddings on grid items can be resolved against either:

  • their own axis (left/right percentages resolve against width, top/bottom resolve against height), or,
  • the inline axis (left/right/top/bottom percentages all resolve against width)

A User Agent must choose one of these two behaviors.

选择任一解析策略不一致:如您所见,Chrome和 Safari 将选择策略 #2,而 IE、Edge 和 Firefox将采用策略#1(这解释了你的错误)。 W3C 还指出:

Note: This variance sucks, but it accurately captures the current state of the world (no consensus among implementations, and no consensus within the CSSWG). It is the CSSWG’s intention that browsers will converge on one of the behaviors, at which time the spec will be amended to require that.

Authors should avoid using percentages in paddings or margins on grid items entirely, as they will get different behavior in different browsers.


解决方案

你能做的就是将圆本身定义为一个伪元素。在这种方法中:

  • 外部 #circle 元素的宽度为 9%,但没有其他元素
  • ::before 伪元素的宽度为 100%,padding-top 为 100%,这将强制它的纵横比为 1:1想要

您更新后的 CSS 将如下所示:

#circle {
  width: 9%;
  margin: auto;
}

#circle::before {
  background: #7FFF00;
  border-radius: 50%;
  width: 100%;
  height: 0;
  padding-top: 100%;
  content: '';
  display: block;
}

请参阅下面的概念验证(或在此 fiddle 中):

#content {
  display: grid;
  grid-template-columns: minmax(13rem, 15%) minmax(85%, 100%);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#circle {
  width: 9%;
  margin: auto;
}

#circle::before {
  background: #7FFF00;
  border-radius: 50%;
  width: 100%;
  height: 0;
  padding-top: 100%;
  content: '';
  display: block;
}

.menu {
  background: #D2691E;
  grid-row-start: 1;
  grid-row-end: 1;
}

.circle-area {
  background: #191970;
  grid-row-start: 1;
  grid-row-end: 1;
  grid-column-start: auto;
  grid-column-end: span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
<body>
  <div id='content'>
    <div class='menu'></div>
    <div class='circle-area'>
      <div id='circle'></div>
    </div>
  </div>
</body>