Victoria
Victoria

Reputation: 505

nested svg inherited sizes

Two mysteries, or maybe they are the same. All the rectangles in the below are filling in for graphics, which have been removed to simplify the description.

Mystery #1: A height for #mbfluid is given, but it is not honored. The #mbfluid rectangle should grow dynamically based on the width of #mbsvg. So mystery #1 is why the height is not honored.

Note that if I give explicit widths for either or both #mbsvg in the CSS or #mbfluid as an attribute, the height is still not honored. Note that the syntax for the height specification for #mbfluid is exactly the same as for #mbfixed which is the expected height. I expected the width of #mbsvg to be the same as its parent, and that would be OK... but in the debugger, #mbfluid is reported as having a huge width. But specifying a width for it doesn't seem to fix the height. Submystery #1 would be how to specify the width of #mbfluid so that it starts 10pt from the left, and extends to the right edge of the containing #mbsvg. I don't think I can use CSS calc for this as width cannot presently be specified via CSS, and I didn't find a similar capability for SVG attributes. But if the height can be fixed, I don't probably care much about the width, as long as it is big enough.

Mystery #2: #mbsvg has a couple sibling divs containing nowrap text. I would like #mbsvg to be the same width as whichever line of text is wider. Multiple instances of #mbsvg will be used with different lines of text, having different widths, and I'm trying to make one #mbsvg that can work in those different locations. I've no idea how to specify the CSS to cause the size of #mbsvg to inherit the size of the wider of the two lines of text. A javascript solution would suffer from the multitude of such groupings expected to be on the page (maybe 500 on the biggest page), and further, the lines of text may be individually switched on and off (one or both being visible) using CSS, so the javascript would have to be rerun, and know which ones are visible, in order to discover the proper size to make the #mbsvg. This system is already functioning nicely, with a fixed-width variety of the #mbsvg, but the responsive #mbsvg would make it much more attractive.

Edit: (regarding Mystery #1) Experimenting more, tried making the height bigger, and exactly 10 times bigger displayed as desired. But this link says that x, y, height, and width attributes use the parent coordinate space, so this looks like a bug... but if so, it is in all the browsers (and at least IE doesn't share all the same SVG code, because it shows a wider #mbsvg, and doesn't crop #mbfluid to the boundary of #mbsvg), because they all show it. The only factor of 10 nearby is in the viewbox aspect ratio, and changing that has an impact, in spite of what it says at the link, which is supposed to be the standard. So now the problem is if I workaround this, how can I do it so that it is immune to the browser vendors fixing this bug (at least, it presently seems to me to be a bug)?

.mbsvg
{
position: relative;
height: 49pt;
background-color: #80ffff;
}
.mbsized
{
height: 100%;
}
.nowrap
{
white-space: nowrap;
}
<svg height="0"><defs>
 <rect id="r1" x="0" y="0" height="10" width="10" />
 <rect id="r2" x="0" y="0" height="10" width="100" />
 <rect id="r3" x="0" y="0" height="250" width="85" />
</defs></svg>
<div>
  <div class="nowrap">This is some text</div>
  <div class="nowrap">This is some other text</div>
  <svg class="mbsvg">
   <use xlink:href="#r1" fill="red"/>
   <svg class="mbfluid" x="10pt" y="16pt" height="17pt"
     viewbox="0 0 10 100" preserveAspectRatio="none">
    <use xlink:href="#r2" fill="yellow"/>
   </svg>
   <svg class="mbfixed" x="0" y="16pt" height="17pt" width="10pt"
     viewbox="0 0 10 10" preserveAspectRatio="none">
    <use xlink:href="#r1" fill="blue"/>
   </svg>
   <svg class="mbsized"
     viewbox="0 0 83 250" preserveAspectRatio="xMidYMid meet">
    <use xlink:href="#r3" fill="green"/>
   </svg>
  </svg>
</div>

Upvotes: 1

Views: 3205

Answers (2)

Victoria
Victoria

Reputation: 505

OK, here is a solution that works for me, but only because the height of the #mbsvg is fixed, which I neglected to mention, although it was shown in the CSS. I found the technique here and have revised it to fit this situation.

The trick is to make #mbsvg an absolutely positioned child of the outer div, and give it a width of 100%. Because it is absolutely positioned, it gets demoted from contributing to the size of the parent, so the other items determine that size (since the parent is floated, it is shrink-to-fit) which is then inherited by #mbsvg. The other items can even be below #mbsvg, as I demonstrated by moving one line of text below it (using a filler div of the same height as #mbsvg to achieve that).

Edit I had length and width swapped in the viewbox value. Turned them around and mystery #1 is totally resolved.

.mbsvg
{
position: relative;
height: 49pt;
background-color: #80ffff;
}
.mbsized
{
height: 100%;
}
.nowrap
{
white-space: nowrap;
}
.flex
{
position: relative;
float: left;
}
.flex > svg
{
position: absolute;
width: 100%;
}
.svgfiller
{
height: 49pt;
}
<svg height="0"><defs>
 <rect id="r1" x="0" y="0" height="10" width="10" />
 <rect id="r2" x="0" y="0" height="10" width="100" />
 <rect id="r3" x="0" y="0" height="250" width="85" />
</defs></svg>
<div class="flex">
  <div class="nowrap">This is some text</div>
  <svg class="mbsvg">
   <use xlink:href="#r1" fill="red"/>
   <svg class="mbfluid" x="10pt" y="16pt" height="17pt"
     viewbox="0 0 10 10" preserveAspectRatio="none">
    <use xlink:href="#r2" fill="yellow"/>
   </svg>
   <svg class="mbfixed" x="0" y="16pt" height="17pt" width="10pt"
     viewbox="0 0 10 10" preserveAspectRatio="none">
    <use xlink:href="#r1" fill="blue"/>
   </svg>
   <svg class="mbsized"
     viewbox="0 0 83 250" preserveAspectRatio="xMidYMid meet">
    <use xlink:href="#r3" fill="green"/>
   </svg>
  </svg>
  <div class="svgfiller"></div>
  <div class="nowrap">This is some other text</div>
</div>

Upvotes: 1

Victoria
Victoria

Reputation: 505

Mystery #1: resolved by using an aspect ratio of 1 for the #mbfluid viewbox value... I can deal with that in the real innards of #mbfluid, with a few changes. Edit I had length and width swapped in the viewbox value. Turned them around and mystery #1 is totally resolved.

Mystery #2: resolved by using wrapping it table-row and using table-cell for each item... seems Firefox (only) figures out that #mbsvg is content to live within the width of the other rows. Since the other browsers do not, this is not a sufficient answer, so will not be marked accepted.

.mbsvg
{
position: relative;
height: 49pt;
background-color: #80ffff;
}
.mbsized
{
height: 100%;
}
.nowrap
{
white-space: nowrap;
}
.flex > div
{
display: table-row;
}
.flex > div > div
{
display: table-cell;
}
.flex > div > svg
{
display: table-cell;
}
<svg height="0"><defs>
 <rect id="r1" x="0" y="0" height="10" width="10" />
 <rect id="r2" x="0" y="0" height="10" width="100" />
 <rect id="r3" x="0" y="0" height="250" width="85" />
</defs></svg>
<div class="flex">
  <div><div class="nowrap">This is some text</div></div>
  <div><div class="nowrap">This is some other text</div></div>
  <div><svg class="mbsvg">
   <use xlink:href="#r1" fill="red"/>
   <svg class="mbfluid" x="10pt" y="16pt" height="17pt"
     viewbox="0 0 10 10" preserveAspectRatio="none">
    <use xlink:href="#r2" fill="yellow"/>
   </svg>
   <svg class="mbfixed" x="0" y="16pt" height="17pt" width="10pt"
     viewbox="0 0 10 10" preserveAspectRatio="none">
    <use xlink:href="#r1" fill="blue"/>
   </svg>
   <svg class="mbsized"
     viewbox="0 0 83 250" preserveAspectRatio="xMidYMid meet">
    <use xlink:href="#r3" fill="green"/>
   </svg>
  </svg></div>
</div>

Upvotes: 0

Related Questions