Flexbox布局中的填充底部/顶部

79

我有一个包含两个项目的flexbox布局。其中一个使用padding-bottom

#flexBox {
  border: 1px solid red;
  width: 50%;
  margin: 0 auto;
  padding: 1em;
  display: flex;
  flex-direction: column;
}
#text {
  border: 1px solid green;
  padding: .5em;
}
#padding {
  margin: 1em 0;
  border: 1px solid blue;
  padding-bottom: 56.25%; /* intrinsic aspect ratio */
  height: 0;
}
<div id='flexBox'>
  <div id='padding'></div>
  <div id='text'>Some text</div>
</div>

当页面被调整大小时,蓝色元素根据其宽度保持纵横比

这适用于Chrome和IE,效果如下:

padding-bottom in chrome and IE on flexbox layout

然而,在FirefoxEdge上,我得到了以下结果(它忽略了蓝盒子上的填充,这是维持纵横比的原因):

padding-bottom in Firefox on flexbox layout

我对弹性盒子太陌生了,无法真正理解这是否应该起作用。弹性盒子的整个目的是调整大小,但我不确定为什么它忽略了固有填充,并给蓝色元素设置绝对大小。

我猜最终我甚至不确定Firefox或Chrome是否在做正确的事情!有哪位Firefox弹性盒子专家能帮忙吗?


以上的解释非常有帮助。为了进一步了解背景和解释,我建议阅读Smashing Magazine的“在响应式iFrame中使嵌入内容正常工作”(https://www.smashingmagazine.com/2014/02/making-embedded-content-work-in-responsive-design/)。这篇文章清晰、简洁地解释了为什么这种填充和div包装器解决方案有效。 - Jess
3个回答

106

2020年9月更新

Firefox和Edge已经按照规范实现了flex元素的边距和填充,这两个属性都是根据包含块的宽度计算的。
就像块级元素一样。

2018年2月更新

Firefox和Edge已经同意更改他们在flex(和grid)项目中顶部、底部边距和填充的行为:

[...] 例如,水平书写模式下左/右/上/下百分比都相对于其包含块的宽度进行解析。[source]

这还没有实现(在FF 58.0.2上测试过)。

2016年4月更新

在2017年5月仍然有效

规范已经更新为:

弹性盒子模型中,对于弹性项目的百分比边距和内边距可以根据以下两种方式解析:

  • 它们自己的轴(左/右百分比相对于宽度,上/下相对于高度),或者
  • 行内轴(左/右/上/下百分比都相对于宽度)

来源:CSS Flexible Box Layout Module Level 1

这意味着Chrome、IE、Firefox和Edge(即使它们没有相同的行为)都遵循规范的建议。

规范还指出:

作者应该完全避免在弹性项目的填充或边距中使用百分比,因为它们在不同的浏览器中会得到不同的行为。[source]


解决方法

您可以将 flex 容器的第一个子元素包装在另一个元素中,并将 padding-bottom 应用于第二个子元素:

#flexBox {
  border: 1px solid red;
  width: 50%;
  margin: 0 auto;
  padding: 1em;
  display: flex;
  flex-direction: column;
}
#text {
  border: 1px solid green;
  padding: .5em;
}
#padding {
  margin: 1em 0;
  border: 1px solid blue;
}
#padding > div {
  padding-bottom: 56.25%; /* intrinsic aspect ratio */
}
<div id='flexBox'>
  <div id='padding'><div></div></div>
  <div id='text'>Some text</div>
</div>

我在现代浏览器(IE,Chrome,FF和Edge)中测试了这个,它们都有相同的行为。由于第二个子元素的配置是“与通常相同的”,我认为旧版浏览器(也支持flexbox布局模块)将呈现相同的布局。


上一个答案

根据specs,Firefox的行为是正确的

解释

与块级元素不同,它们根据容器的宽度计算其百分比边距/填充,在弹性项目上:

弹性项目上的百分比边距和填充总是相对于它们各自的尺寸进行解析;与块级元素不同,它们不总是相对于其包含块的内联尺寸进行解析。

source dev.w3.org

这意味着padding-bottom/top和margin-bottom/top是根据容器的高度计算的,而不是像非弹性盒子布局中那样根据宽度计算。

由于您没有在父弹性项目上指定任何高度,因此子元素的底部填充应该为0px。

这里有一个fiddle示例,父容器设置了固定高度,展示了padding bottom根据display:flex;容器的高度计算的情况。

@web-tiki 你好,我也是Flex的新手,刚刚注意到这个问题。请问,Chrome/IE的行为是不正确的吗?如果是这样的话,使用百分比的Padding和Margin在Flex中就完全没有用了! - Terence Chow
1
关于Firefox的此错误,正在此处处理,并且显然被归类为无效,但是似乎CSS规范已经更新以允许我们许多人正在寻找的行为。我们现在只需要确保提出问题即可 ;) - zanona
1
当前 CSSWG草案 表示:"左/右/上/下百分比都相对于它们所在的包含块的宽度计算"。 - Qtax
1
这个问题中,Edge和FF已经同意(大约在2018年1月)采用width/Blink行为,并将对其进行实现。 +1 - Qtax
1
@AleksandrH,我已经更新了答案。由于火狐和Edge都已经实现了同样的行为,所以我会把这个答案留在这里供参考。 - web-tiki
显示剩余4条评论

37

这个被接受的答案是正确的,但是我通过使用一个伪元素来改进解决方案,而不是向HTML添加一个新元素。

例如:http://jsfiddle.net/4q5c4ept/

HTML:

<div id='mainFlexbox'>
  <div id='videoPlaceholder'>
    <iframe id='catsVideo' src="//www.youtube.com/embed/tntOCGkgt98?showinfo=0" frameborder="0" allowfullscreen></iframe>
  </div>
  <div id='pnlText'>That's cool! This text is underneath the video in the HTML but above the video because of 'column-reverse' flex-direction.    </div>
</div>

CSS:

#mainFlexbox {
  border: 1px solid red;
  width: 50%;
  margin: 0 auto;
  padding: 1em;
  display: flex;
  flex-direction: column-reverse;
}
#pnlText {
  border: 1px solid green;
  padding: .5em;
}
#videoPlaceholder {
  position: relative;
  margin: 1em 0;
  border: 1px solid blue;
}
#videoPlaceholder::after {
  content: '';
  display: block;
  /* intrinsic aspect ratio */
  padding-bottom: 56.25%;
  height: 0;
}
#catsVideo {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

2
这是一个非常聪明和非破坏性的变通方法。在我看来,它还比之前的建议更具优势。 - zanona
完美的解决方案!救命稻草。 - nsilva

-3

我使用了vh而不是%在Safari、Firefox和Edge中完美地工作了。


1
vh 是一个视口单位,与元素或其父级无关。它适用于元素相对于视口大小调整的情况,但不适用于一般情况(也不适用于此问题)。 - alpipego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接