flexbugs icon indicating copy to clipboard operation
flexbugs copied to clipboard

Auto-sizing images and inline SVG as flex children

Open AmeliaBR opened this issue 9 years ago • 5 comments

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).

AmeliaBR avatar Nov 08 '16 21:11 AmeliaBR

Is a height attribute sufficient for an explicit cross-axis size?

tigt avatar Aug 04 '18 22:08 tigt

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.

selrond avatar Jan 17 '19 15:01 selrond

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.

cdoublev avatar Jul 25 '19 08:07 cdoublev

Here’s 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>
Screen Shot 2021-03-04 at 12 01 56 PM

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>
Screen Shot 2021-03-04 at 12 02 11 PM

It seems you can workaround this issue by adding Apple’s nonstandard height: intrinsic constant in addition to height: auto.

Live examples: https://observablehq.com/d/405e33d0a2be5a73

mbostock avatar Mar 04 '21 20:03 mbostock

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.

cdoublev avatar May 06 '21 13:05 cdoublev