In a single row/column flex container, the child items will stretch to fit the full height/width (cross-axis) and then determine their size in the opposite (flex main axis) direction. However, browsers are currently inconsistent when the flex items are images. Normally, once you set an image's size in one direction, an auto value for the other direction is calculated based on the aspect ratio. But Chrome and Firefox
Images do get a minimum size, in all browsers, based on the aspect ratio. If you don't set min-width
or min-height
to 0 (or change the overflow
settings), they will have a minimum size based on the aspect ratio and the cross axis size. However, Chrome & Firefox do not apply the minimum sizing rule to inline SVG, but Edge & Safari do.
To make things even more confusing, Chrome & Firefox can't even agree on what they do instead: Chrome treats the elements as 0 width/height (if flex-grow
is 0, otherwise they grow equally). Firefox treats them as 100% width/height (if flex-shrink
is 0, otherwise they shrink equally).
See spec bug https://github.com/w3c/csswg-drafts/issues/694 for more details.
Avoid the issue by:
Always making sure image / SVG elements in a flex container have an explicit size in the cross axis (i.e., height for a flex row, width for a flex column).
Expressly override the minimum size constraint with min-width: 0
(for row) or min-height: 0
(for column).
Is a height
attribute sufficient for an explicit cross-axis size?
I have inline svg
with no width / height set as a flex item and am experiencing this in Chrome and Safari - svg
appears to have 0x0 dimensions.
Setting width / height (or both) through attributes or css properties seems to fix it.
How do you prevent an SVG which has a viewBox, no width/height, and is a flex column item, to expand the width of its (flex) container in Firefox?
Eg.: a site-wide vertical nav bar (an inline flex container) covering the full viewport's height, containing an SVG logo that should fill the available space along the cross-axis, but not extend it.
I tried wrapping the SVG, but it doesn't work. Worse: if the SVG has a cross-axis padding, it will now overflow its container.
Demo: https://codepen.io/creative-wave/pen/zgqXYQ?editors=1000
Edit 1: the demo shows an SVG contained by a flex item, and isn't a flex item itself, to demonstrate another issue related to the overflow created by padding/border (even if box-sizing: border-box
is defined), but you can remove this container and it will demonstrate the issue described above.
Edit 2: a fix for the padding issue when it's a child of an inline flex column item (the issue no longer exists when it's an inline flex column item) is max-width: 100%
on the svg
.
Here鈥檚 a simple reproduction of this issue (I believe) in Safari:
<div style="display: flex; width: 300px;">
<svg width="800" height="200" style="height: auto; width: 100%;">
<rect fill="steelblue" width="800" height="200"></rect>
<text text-anchor="middle" dy="0.35em" x="50%" y="50%">800 x 200</text>
</svg>
</div>
Safari shows this as a 300脳200 image, while Chrome scales it down to 300脳75 as expected, preserving the aspect ratio. With a viewBox, you get whitespace around the 300脳75 rect, but the SVG is still 300脳200.
<div style="display: flex; width: 300px;">
<svg width="800" height="200" viewBox="0 0 800 200" style="height: auto; width: 100%;">
<rect fill="steelblue" width="800" height="200"></rect>
<text text-anchor="middle" dy="0.35em" x="50%" y="50%">800 x 200</text>
</svg>
</div>
It seems you can workaround this issue by adding Apple鈥檚 nonstandard height: intrinsic constant in addition to height: auto.
Live examples: https://observablehq.com/d/405e33d0a2be5a73
I created this codepen to visualize the differences between browsers, if it can help anyone figure out the issues that still stuck me for hours, 2 years after my previous comment.
Most helpful comment
I have inline
svg
with no width / height set as a flex item and am experiencing this in Chrome and Safari -svg
appears to have 0x0 dimensions.Setting width / height (or both) through attributes or css properties seems to fix it.