为啥弹性项目的宽度和高度会影响弹性项目的呈现方式?

Posted

技术标签:

【中文标题】为啥弹性项目的宽度和高度会影响弹性项目的呈现方式?【英文标题】:Why does width and height of a flex item affect how a flex item is rendered?为什么弹性项目的宽度和高度会影响弹性项目的呈现方式? 【发布时间】:2017-12-06 07:09:01 【问题描述】:

根据是否设置了heightwidth 属性,弹性框中具有max-height 样式的图像呈现不同的效果。

具有属性的那一个,设置为图像的真实宽度/高度,在保留其纵横比的情况下进行渲染,但没有属性的那一个尊重max-height,并且看起来被压扁了。

.flex-parent 
  display: flex;
  max-height: 10vh;
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img   src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

这就是在 Chrome 58 中的显示方式(在 Firefox 54 中也是如此)。

为什么它们的渲染方式不同?管理这种行为的规则是什么?

我的(显然是不正确的)理解是height和width属性会覆盖图片加载时发现的固有的height和width,如果height和width属性等于图片的尺寸,在渲染上应该没有区别一旦图像加载完毕。

上下文是用响应式图像制作一个页面,其中每个图像

可以有独特的原始尺寸 加载时不会导致回流,即在初始渲染时保留正确的空间(因此使用高度和宽度属性) 可以一次在屏幕上显示所有内容(因此我在 CSS 中使用 vh

青蛙图片来自https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg

【问题讨论】:

您将 max-height 分配给父 div,在 img 标签上分配该高度 flex-parent img:first-of-type 我使用 first-of-type 只影响第一个 img。第二张图片有 heightwidth 所以它看起来是正确的纵横比,但第一个是渲染宽度不是纵横比 你可以在这里看到一个例子jsfiddle.net/Lokeshg27/tp53tv82/23 【参考方案1】:

弹性容器的初始设置是align-items: stretch

这意味着弹性项目将扩展到容器的cross axis。

在行方向容器中,就像在问题中一样,交叉轴是垂直的。

这意味着项目(在本例中为图像)将覆盖容器的整个高度。

但是,当弹性项目具有定义的交叉大小时,它将覆盖 stretch 默认值。

来自规范:

8.3. Cross-axis Alignment: the align-items and align-self properties

Flex项目可以在当前行的横轴上对齐 flex 容器,类似于justify-content,但在垂直方向 方向。

stretch

如果弹性项目的交叉尺寸属性计算为auto,并且 两个横轴边距都不是auto,弹性项目是 拉伸。

这是关键语言:

如果弹性项目的交叉尺寸属性计算为auto

这就是规范定义“交叉尺寸属性”的方式:

flex 项目的宽度或高度,以叉号为准 尺寸,是项目的交叉尺寸cross size 属性是 在交叉维度中的widthheight 中的任意一个。

https://www.w3.org/TR/css-flexbox-1/#cross-size-property


因此,您的代码似乎按照规范中的定义运行。

这就是你所拥有的:

.flex-parent 
  display: flex;
  max-height: 10vh;
<div class="flex-parent">
  <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img   src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

第一张图片在 CSS 或 html 中没有定义宽度(主要尺寸)或高度(横向尺寸)。因此,它的交叉大小计算为auto

此声明:

如果弹性项目的交叉尺寸属性计算为auto

...为真,align-items: stretch 生效。

图像在容器的高度上展开,即 10 像素。

第二张图片有明确的尺寸。十字尺寸在 HTML (height="240") 中定义。

现在这个声明:

如果弹性项目的交叉尺寸属性计算为auto

... 为假,align-items: stretch 被覆盖。 HTML 以height 属性为准。

关于第二张图片的两个注意事项:

    图像忽略容器上的 max-height 限制,因为 CSS 中的初始设置是 overflow: visible。 HTML widthheight 属性映射到它们各自的 CSS 属性。因此,height="240" 会覆盖 height: auto 默认值。有关规范参考,请参见下文。*

在 flex 容器中渲染图像时还需要考虑另外两个问题。

    弹性项目的默认最小尺寸。此设置可防止弹性项目缩小到其内容大小以下。阅读这篇文章以获取完整的详细信息:

    Why doesn't flex item shrink past content size?

    主要浏览器之间的不同行为。 Firefox、Chrome、Safari、Edge 和 IE11 并不总是以相同的方式将图像渲染为弹性项目。阅读这篇文章了解更多详情:

    Flex in Firefox shrinks images automatically, but not in Chrome

考虑到以上所有因素,这是我建议的解决方案:

.flex-parent 
  display: flex;
  max-height: 50vh; /* adjusted for demo */


.flex-parent 
  min-width: 0;


img 
  width: 100%;
  height: auto;
<div class="flex-parent">
  <div>
    <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
  <div>
    <img   src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
</div>

*HTML widthheight 属性映射到它们各自的 CSS 属性。因此,当指定时,它们会覆盖 CSS 默认值。来自 HTML5 规范:

10.4.3 Attributes for embedded content and images

appletembediframe 上的 widthheight 属性, objectvideo 元素,以及带有 typeinput 元素 图像按钮状态中的属性,并且要么代表一个 图像或用户期望最终代表图像, 映射到维度属性分别在元素上widthheight

10.2 The CSS user agent style sheet and presentational hints

当下面的文字说元素上的属性映射到 维度属性(或属性),表示如果元素有 一个属性集,并且使用 rules for parsing dimension values 解析该属性的值不会产生错误,那么用户代理应该使用 将维度解析为 presentational hint 的值 属性,如果尺寸为像素长度,则值为 是一个整数,如果 维度是一个百分比。

【讨论】:

【参考方案2】:

尝试阅读 w3c flexbox 规范并偶然发现this。它说

对于每个维度,如果弹性容器内容的那个维度 盒子是确定的尺寸,使用它;如果 flex 的那个尺寸 容器的大小在最小或最大内容约束下, 该维度中的可用空间就是该约束。

否则,从该维度中 flex 容器的可用空间中减去 flex 容器的边距、边框和填充,并使用该值,这可能会导致无限值。

希望这会有所帮助。

【讨论】:

【参考方案3】:

这里你写了 max-height:10vh, vh 不支持任何浏览器,除了最新的 ios 6。这适用于所有与视口相关的长度单位。 使用其他值而不是 Vh 这将正常工作。 请阅读此博客https://css-tricks.com/the-lengths-of-css/。

.flex-parent 
  display: flex;
  max-height:  max-content;
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img   src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

【讨论】:

您指向的文章是 2013 年的,在互联网时代,大约是十年前。 caniuse.com/#search=vw 这显示了与视口相关的测量改进了多少。我个人非常喜欢在某些情况下使用 vh/vw。【参考方案4】:

问题在于您设置最大高度的位置。默认情况下不继承 css 属性 max-height。您的 css 声明会创建一个占视口高度 10% 的 div。未设置尺寸的图像会根据其父尺寸缩小。您设置隐式尺寸的图像始终是那些尺寸。根据 div 的大小,它可能会溢出。如果将 max-height 属性放在第一张图片上,它应该调整大小以保持纵横比相同。

【讨论】:

以上是关于为啥弹性项目的宽度和高度会影响弹性项目的呈现方式?的主要内容,如果未能解决你的问题,请参考以下文章

flex弹性盒模型

为啥弹性项目宽度随着 flex-grow 增长:0 [重复]

将弹性项目保留在父容器内

为啥弹性项目不缩小超过内容大小?

css3盒模型和弹性布局的相关属性

弹性项目是不是可以与它们上方的项目紧密对齐?