为什么Flex项目的宽度和高度会影响Flex项目的渲染方式? [英] Why does width and height of a flex item affect how a flex item is rendered?
问题描述
具有 max-height
样式的flexbox中的图像根据其是否具有高度
和 width 属性设置。
其中与属性设置为图像的真实宽度/高度,呈现其纵横比保存,但没有属性的方面尊重 max-height
,并出现压扁。
.flex-parent {display:flex; < div class = 柔性父> < 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 WIDTH = 320 HEIGHT = 240 SRC = https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg >< / div>
它类似于Firefox 54)。
为什么它们呈现不同?这个行为的规则是什么?
我的(明显不正确的)理解是高度和宽度属性会覆盖图像加载时发现的内在高度和宽度,如果height和width属性等于图片的尺寸,那么一旦图片加载,渲染应该没有区别。
上下文使用响应图像,其中每个图像
- 可以具有独特的原始尺寸
- 不会导致回流加载,即正确的空间保留在初始渲染(因此使用高度和宽度的属性)
- 可以一次适合所有的屏幕(因此我搞乱了
vh
在CSS中)
青蛙图像来自< A HREF = https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg 相对= nofollow noreferrer> https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg 一个flex容器的初始设置是
flexbox-1 /#align-items-propertyrel =noreferrer> align-items:stretch
。
这意味着flex项目将在容器的横轴上展开。
在一个行方向的容器中,就像问题一样,横轴是垂直的。
意味着物品(在本例中为图像)将覆盖容器的整个高度。
但是,当flex项目具有定义的交叉大小时,将覆盖 stretch
default。
从规范:
b $ b这是关键语言:
$ b
如果flex项目的cross size属性计算到
auto
这就是spec定义cross size property :
Flex项目的宽度或高度(以交叉
为准)是项目的交叉大小。无论是width
还是height
, cross size属性都是
交叉维度。
https://www.w3.org/TR/css-flexbox-1/#cross-size-property
< blockquote>
所以你的代码看起来像规范中定义的一样。
$ b
.flex-parent {display : 柔性; < div class = 柔性父> < 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 WIDTH = 320 HEIGHT = 240 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
。
这句话:
如果flex项目的cross size属性计算为
auto
$ b...是真实的,
align-items:stretch
生效。
图片在容器的高度上展开,为10px。
第二张图片 。交叉大小在HTML中定义(height =240
)。
现在这个声明: p>
如果flex项目的cross size属性计算为
auto
...为false,并且
align-items:stretch 被覆盖。 ,
有关第二张图片的两个注意事项:
$height
b $ b
- 图像忽略容器上的
max-height
限制,因为CSS中的初始设置是overflow:visible
。
- HTML
宽度
和高度
属性映射到它们各自的CSS属性。因此,height =240
会覆盖height:auto
默认值。 *
还有两个其他问题需要考虑在flex容器中呈现图像。
弹性项目的默认最小大小。此设置可防止弹性项目缩小到其内容的大小以下。阅读这篇文章的全部细节:
主要浏览器之间的行为有所不同。 Firefox,Chrome,Safari,Edge和IE11并不总是以同样的方式将图像渲染为弹性项目。阅读这篇文章的更多细节:
考虑到以上所有因素,以下是我建议的解决方案:
.flex-parent {display:flex;最大高度:50vh; / *调整为演示* /} 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 WIDTH = 320 HEIGHT = 240 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>
$ b $ hr b
HTML
width
和height
属性映射到它们各自的CSS属性。因此,指定时,它们将覆盖CSS默认值。从HTML5规范:
$ b $宽度
和高度
属性applet
嵌入,
iframe
,
object
或视频
元素,以及输入
元素,其中在图像按钮状态下,code>
属性,并且要么表示
图像,要么用户期望最终表示图像,映射到维度属性的
和
height
> 10.2 CSS用户代理样式表和presentationa l
hints
当下面的文字说明元素上的一个属性映射到
维度属性(或属性),则表示如果元素具有
属性集,并使用规则
用于分析维度
值不会产生错误,那么用户代理预计将使用
解析的维度作为表示的值提示为
属性,如果维度
是一个整数,则给定值为像素长度,如果
维度为百分比,则给出的值为百分比。
An image in a flexbox that has a max-height
style appears to render differently depending on whether it has its height
and width
attributes set.
The one with the attributes, set to the true width/height of the image, renders with its aspect ratio preserved, but the ones without the attributes respects the max-height
and appear squashed.
.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 width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
This is how is appears in Chrome 58 (and it appears similarly in Firefox 54).
Why do they render differently? What are the rules that govern this behaviour?
My (obviously incorrect) understanding is that height and width attributes overwrite the intrinsic height and width that is found when the image loads, and if the height and width attributes equal the dimensions of the image, there should be no difference in rendering once the image has loaded.
The context is making a page with responsive images, where each image
- can have unique original dimensions
- does not cause a reflow when it's loaded, i.e. the correct space is reserved on initial render (hence using height and width attributes)
- can fit all on screen at once (hence me messing with
vh
in the CSS)
The frog image is from https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg
An initial setting of a flex container is align-items: stretch
.
That means that flex items will expand across the cross axis of the container.
In a row-direction container, like in the question, the cross axis is vertical.
That means the items (images, in this case) will cover the full height of the container.
However, when a flex item has a defined cross size, that overrides the stretch
default.
From the spec:
8.3. Cross-axis Alignment: the
align-items
andalign-self
propertiesFlex items can be aligned in the cross axis of the current line of the flex container, similar to
justify-content
but in the perpendicular direction.
stretch
If the cross size property of the flex item computes to
auto
, and neither of the cross-axis margins areauto
, the flex item is stretched.
This is the key language:
If the cross size property of the flex item computes to
auto
And this is how the spec defines "cross size property":
The width or height of a flex item, whichever is in the cross dimension, is the item’s cross size. The cross size property is whichever of
width
orheight
that is in the cross dimension.
So your code appears to be playing out as defined in the spec.
This is what you have:
.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 width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
The first image has no defined width (main size) or height (cross size), either in the CSS or the HTML. Its cross size, therefore, computes to auto
.
This statement:
If the cross size property of the flex item computes to
auto
... is true, and align-items: stretch
goes into effect.
The image expands across the height of the container, which is 10px.
The second image, however, has explicit sizing. The cross size is defined in the HTML (height="240"
).
Now this statement:
If the cross size property of the flex item computes to
auto
... is false, and align-items: stretch
is overridden. The HTML height
attribute prevails.
Two notes about the second image:
- The image ignores the
max-height
limit on the container because an initial setting in CSS isoverflow: visible
. - The HTML
width
andheight
attributes map to their respective CSS properties. Hence,height="240"
overrides theheight: auto
default. See below for the spec references.*
There are two other issues to consider when rendering images in a flex container.
The default minimum size of flex items. This setting prevents flex items from shrinking below the size of their content. Read this post for full details:
Varying behavior among major browsers. Firefox, Chrome, Safari, Edge and IE11 don't always render images as flex items in the same way. Read this post for more details:
Considering all factors above, here's my suggested solution:
.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 width="320" height="240" 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>
*The HTML width
and height
attributes map to their respective CSS properties. Hence, when specified, they override the CSS defaults. From the HTML5 spec:
10.4.3 Attributes for embedded content and images
The
width
andheight
attributes onapplet
,embed
,iframe
,object
orvideo
elements, andinput
elements with atype
attribute in the Image Button state and that either represents an image or that the user expects will eventually represent an image, map to the dimension propertieswidth
andheight
on the element respectively.10.2 The CSS user agent style sheet and presentational hints
When the text below says that an attribute on an element maps to the dimension property (or properties), it means that if the element has an attribute set, and parsing that attribute's value using the rules for parsing dimension values doesn't generate an error, then the user agent is expected to use the parsed dimension as the value for a presentational hint for properties, with the value given as a pixel length if the dimension was an integer, and with the value given as a percentage if the dimension was a percentage.
这篇关于为什么Flex项目的宽度和高度会影响Flex项目的渲染方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!