图像弹性项目在弹性盒子中无法缩小高度

10

我有一个弹性容器,其中包含一个 img 弹性项目。

我希望这个 img 忽略其固有高度 (90px),以便高度可以缩小以匹配兄弟弹性项目的高度(根据默认的 align-items: stretch 样式)。

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class="container">
    <img class="item" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class="item">
        <div class="content"></div>
    </div>
</div>

如果我们将 img 替换为 div,就能看到期望的行为:

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.dynamicHeightContent {
    width: 120px;
    height: 100%;
    background-color: green;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class="container">
    <div class="item">
        <div class="dynamicHeightContent"></div>
    </div>
    <div class="item">
        <div class="content"></div>
    </div>
</div>

我尝试了在 img 上使用 min-height: 0,但没有效果。

  • img 有什么特殊的行为,而 div 没有?
  • 我们如何取消 img 的特殊行为,使其像其他弹性项(如 div)一样行为?如果没有办法取消,是否有推荐的解决方案?

请注意,虽然 img 不会缩小其高度,但它似乎会增加

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.content {
    width: 200px;
    height: 300px;
    background-color: hotPink;
}
<div class="container">
    <img class="item" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class="item">
        <div class="content"></div>
    </div>
</div>

注意:我很高兴忽略图片的宽高比。我计划通过使用 "object-fit:cover" 来避免扭曲图片。

把图像包裹在一个 div 中并观察差异... - kukkuz
哦,我明白了,图像不会缩小到90像素的原始高度以下,这是有道理的,因为那是弹性项的内容。 - Huangism
3个回答

3
请注意,在您的示例中,itemflex item 而不是 content - 您应该在此处检查 itemstretch 行为。
我们如何取消的特殊行为,使其表现像其他弹性项目(比如
)一样呢?
它表现得像其他弹性项目 - <img>作为弹性项目可能不太有用,但是拉伸行为正常工作:
  • 如果图像的高度比item更高,则item将被拉伸到图像的高度。
  • 如果图像的高度比item低,则图像将被拉伸content的高度,并破坏其宽高比。
请参考下面的演示:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
}
<h2>Small content</h2>
<div class="container">
  <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
  <div class="item">
    <div class="content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class="container">
  <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
  <div class="item">
    <div class="content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

我尝试在上使用min-height: 0,但没有效果。 min-height: 0应用于列弹性盒子沿着弹性方向以覆盖默认的自动行为(对于行方向,该属性是min-width)-这在交叉轴中不起作用。您可以在下面看到详细信息和一些示例: Flexbox affects overflow-wrap behaviorFlexbox resize and scrollable overflowWhy don't flex items shrink past content size?

将图像放入容器中

现在将<img>标签放入一个div中,同样的情况下,stretch行为仍然很好:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
}
<h2>Small content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

现在的区别在于,您现在可以成功地在图像上使用object-fit(如果它是flex item,则无法正常工作):

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<h2>Small content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>


我希望这张图片可以忽略它固有的高度(90px),以便高度可以缩小以匹配兄弟元素的 flex 项目高度。唯一忽略图像高度的方法是在图像包装器上使用定位:将图像与其包装器相对地 绝对 定位,您可以给图像包装器一个宽度或在 item 上给出 flex: 1 以获得半个可用宽度水平方向。请参见下面的演示:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
  flex: 1; /* equal width for items */
}

.content {
  width: 200px;
  background-color: hotPink;
}

.item:first-child { /* image container */
  position: relative;
}

img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute; /* position absolutely */
  top: 0;
  left: 0;
}
<h2>Small content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class="container">
  <div class="item">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class="item">
    <div class="content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>


1
这很有道理,谢谢。很遗憾 position: absolute 的技巧是必要的。我怀疑这将是开发人员经常遇到的问题。感觉我们需要在 CSS 中添加一种声明性方式来解决这个问题,这样我们就不必使用这些 hack 了。我会关注这个问题得到多少关注 :-) - Oliver Joseph Ash

1
我认为你的观点是错误的。
图片本身高度为90像素,这意味着flex项的内容也有90像素高(因为你的图片是flex项)。因此,右侧的div与图像高度匹配,因为它比div的高度更高,而不是相反。
可以将其看作将flex项(图像)的高度设置为90像素。因此,除非将其设置为较小的高度,否则它不会缩小到低于这个高度。尽管您没有明确将图像高度设置为90像素,但它自然地为90像素,因此隐式设置导致了混淆。因此,虽然它在高度方面会伸展超过90像素,但它不会低于flex项内容的高度。
如果您将其替换为一个div并且它能像您想象的那样工作,那是因为未设置flex项(.item) div的高度。

这很有道理,但我本来期望有一种方法可以忽略图像的固有大小/高度,例如 min-height: 0。另外,有什么推荐的解决方法吗?这是一个非常常见的用例。 - Oliver Joseph Ash
再次强调,图像的尺寸作为 flex 项的内容,可以将图像视为一块文本区域,该文本区域占据了 90 像素的高度空间。如果您想要它更小,您需要设置一个高度。 - Huangism
关于这张图片的问题是它是一个高度为90像素的实心块,就像一个90像素高的字母一样,所以它不能缩短到比这更小,因为这是它能达到的最小尺寸。 - Huangism
这是一个很好的看法。但是当您使用object-fit时,图像可以在任何高度下工作。因此,CSS可能有一些机制来忽略固有高度,这也是有道理的。 - Oliver Joseph Ash
我希望我的解释有意义,这是我能够合乎逻辑地解释这个的唯一方式。 - Huangism

0

虽然这不是你所问的答案,但 div 和 img 实际上表现相同,即如果有比高度更高的内容,则会增加高度。

例如:

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.dynamicHeightContent {
    width: 120px;
    height: 100%;
    background-color: green;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class="container">
    <div class="item">
        <div class="dynamicHeightContent">
        akhsdjahskd<br>
        ajkhsdkjhasd<br>
        ajshdkahsd<br>
        ajsgdjgad<br>
        ajshdasjdh<br>
        </div>
    </div>
    <div class="item">
        <div class="content"></div>
    </div>
</div>

由于您坚持认为 object-fit 可以解决此问题,您可以尝试这样做,正如您所看到的,只有在设置高度和宽度时,object-fit 才有效,否则浏览器会尝试保持它的"纵横比",只需尝试从 CSS 中删除高度或宽度(一次一个),您将看到这种效果。

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

img.item {
    height: 50px;
    width: 200px;
    object-fit: cover;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class="container">
    <img class="item" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class="item">
        <div class="content"></div>
    </div>
</div>


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