4

I have a two column grid. The first column has a width of auto. The second has a width of 1fr.

The first is a svg image with a height of 100%. Its width is generated based on that.

The second is a div with a lightblue background.

#grid {
  grid-template: 1fr / auto 1fr;
  grid-template-areas: "left right";
}
<div id="grid" style="display: grid; height: 200px; width: 400px; border: 1px solid black;">
  <svg style="grid-area: left; height: 100%;" viewBox="0 0 20 20">
    <ellipse fill="blue" rx="10" ry="10" cx="10" cy="10"></ellipse>
  </svg>
  <div style="grid-area: right; background-color: lightblue;"></div>
</div>

This looks different in firefox, chrome and safari respectively (only chrome gives me what I what):

Firefox:

enter image description here

Chrome:

enter image description here

Safari:

enter image description here

I've been told that, like flexbox, I must set the min-width property the container of the svg. (I've tried putting those values with a overflow on the entire tree, too)

#grid {
  grid-template: 1fr / auto 1fr;
  grid-template-areas: "left right";
}
<div id="grid" style="display: grid; height: 200px; width: 400px; border: 1px solid black;">
  <div style="min-width: 0; height: 100%; grid-area: left;">
    <svg style="height: 100%;" viewBox="0 0 20 20">
      <ellipse fill="blue" rx="10" ry="10" cx="10" cy="10"></ellipse>
    </svg>
  </div>
  <div style="grid-area: right; background-color: lightblue;"></div>
</div>

This again looks different in the three browsers. This time firefox gives me what I want but chrome and safari give my blue circle no room.

Firefox:

enter image description here

Chrome:

enter image description here

Safari:

enter image description here

Is there a way to give an svg grid item a width of auto and have it act sanely when the SVG item's width is generated from its height?


Bizarrely, flexbox gives me what I want in all three browsers:

<div style="display: flex; height: 200px; width: 400px; border: 1px solid black;">
  <div style="min-width: 0; height: 100%;">
    <svg style="height: 100%;" viewBox="0 0 20 20">
      <ellipse fill="blue" rx="10" ry="10" cx="10" cy="10"></ellipse>
    </svg>
  </div>
  <div style="flex-grow: 1; background-color: lightblue;"></div>
</div>

I am incredibly confused.


I've found an unsatisfactory solution: use a timeout to unset the width of the svg to force safari and chrome to recalculate:

setTimeout(_ => {
  document.querySelector("svg").style.width = "unset"
})
#grid {
  grid-template: 1fr / auto 1fr;
  grid-template-areas: "left right";
}
<div id="grid" style="display: grid; height: 200px; width: 400px; border: 1px solid black;">
  <div style="min-width: 0; height: 100%; grid-area: left;">
    <svg style="height: 100%; width: 0;" viewBox="0 0 20 20">
      <ellipse fill="blue" rx="10" ry="10" cx="10" cy="10"></ellipse>
    </svg>
  </div>
  <div style="grid-area: right; background-color: lightblue;"></div>
</div>
mmm111mmm
  • 3,607
  • 4
  • 27
  • 44
  • you run into a complex calculation. Many values depend on each other (auto depend on the width, the height depend on the parent height, the width on the height, etc) – Temani Afif Aug 01 '20 at 21:16
  • @TemaniAfif At least in my mind, it doesn't seem complex: the svg calculates its width from its height and it gets its height from its parent. The fact that flexbox does it perfectly confuses me. – mmm111mmm Aug 01 '20 at 21:29
  • In flexbox you don't have grid tracks so you don't have the complexity of the *auto* value that need to be calculated so the height is based on the parent then the width is set and the div will fill the remaining width. In CSS grid, each element is inside a track (https://www.w3.org/TR/css-grid-1/#grid-track-concept) so you have the parent element, the tracks and the grid items (3 layers). In flexbox there is only 2 layers (the parent and the flex items). – Temani Afif Aug 01 '20 at 21:43
  • @TemaniAfif Thanks. I would have thought the track gets its width, in my case, from my SVG. But I understand it's more complex. You seem to know a lot about the spec. Do you believe my question will yield an answer? – mmm111mmm Aug 01 '20 at 21:49
  • it's difficult when we face such behavior (each browser giving a different result) because we don't really know which one is supposed to be the correct one but yes you may have an answer. Simply wait, there is some CSS wizards around ;) – Temani Afif Aug 01 '20 at 22:03
  • also to understand how the calculation is complex and buggy, check the second snippet on chrome and resize the window a lot. You will notice the blue coloration growing because on each resize your trigger a new caclulation based on previous values giving strange results. Another thing: comment/uncomment the height:100% of the SVG and you will get the correct output on chrome (still the second snippet) – Temani Afif Aug 01 '20 at 22:14
  • @TemaniAfif Yes I noticed that. That's why I edited in a unsatisfactory solution: use a timeout to force a redraw of the svg. – mmm111mmm Aug 01 '20 at 22:19
  • This has a lot more to do with your SVG not having width and height attributes than CSS layout. Having viewbox only on SVG, and no outside CSS to govern the SVG size, it ends up being 0. Your examples will behave more predictably if you use something that isn't "invisible". Flexbox shows the circle because you explicitly stated the width of each flex item, and grid doesn't because you stated the cells width to depend, and SVG without width, or CSS size can't stretch it. – prkos Dec 31 '22 at 15:15

0 Answers0