GOAL:
I am trying to get an INLINE SVG
element to fill the full available width of the parent element. I can achieve the same effect easily using an img
and object
tag to reference the svg file, but I want to use inline svg
because I am animating the svg inner elements with javascript.
PROBLEM:
I can achieve this in Firefox and with some tweaks also in Chrome, but safari and IE9 & IE10 won't play ball.
MAIN QUESTION:
Is there a cross browser solution for responsive INLINE SVG: View the example in IE9 & 10 and -webkit-Safari and notice the unrequired extra height within SVG element (cyan color).
http://jsfiddle.net/David_Knowles/9tUAd/
<div class="block">stuff</div>
<div class="wrap">
<svg version="1.1" baseProfile="basic" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 550 350" xml:space="preserve" preserveAspectRatio="xMinYMin meet">
<rect x="0" y="0" width="550" height="350"/>
<polyline points="0,0 0,350 550,350"/>
<text x="0" y="50%" fill="#ffffff" stroke="none" width="100%">The text</text>
</svg>
</div>
<div class="block">stuff</div>
We use viewBox to make the SVG image scalable. viewBox = “0 0 100 100”: defines a coordinate system having x=0, y=0, width=100 units and height=100 units. Thus, the SVG containing a rectangle having width=50px and height=50px will fill up the height and width of the SVG image, and all the dimensions get scaled equally.
Remove height and width attributes For our purposes, the most important aspect is the removal of the width and height attributes that most applications include automatically. This makes the SVG fully responsive in modern browsers.
Once you add a viewBox to your <svg> (and editors like Inkscape and Illustrator will add it by default), you can use that SVG file as an image, or as inline SVG code, and it will scale perfectly to fit within whatever size you give it. However, it still won't scale quite like any other image.
To specify the coordinates within the SVG image independently of the scaled size of the image, use the viewBox attribute on the SVG element to define what the bounding box of the image is in the coordinate system of the image, and use the width and height attributes to define what the width or height are with respect ...
The first problem is that you are setting your .svg-wrap
div to 100% height. 100% of what? In this case, that div's parent element is the body element. When you've got block-level content that's 100% of the body's height, and other in-flow elements, you're always going to have a vertical scrollbar. because you will always have contents of 100% + your .stuff
elements. Just as a general tip, constant overflow like this should be the tipoff that something is wonky in your css.
Continuing further into the DOM, the 100% height declaration on your svg
element is forcing the svg
to expand to the overly tall wrapper. And that's another part of the culprit.
The solution I use involves intrinsic ratios. CSS like this:
.svg-wrap {
background-color:red;
height:0;
padding-top:63.63%; /* 350px/550px */
position: relative;
}
svg {
background-color: cyan;
height: 100%;
display:block;
width: 100%;
position: absolute;
top:0;
left:0;
}
http://jsfiddle.net/pcEjd/
Tested in latest, FF, Chrome, Safari, (though not IE).
The downsides of this approach are that:
a) you have to precalculate ratios for all your boxes, or write a script that does so. Not too bad.
b) you can't use border-box
globally with the star selector, or if you do you need to override box-sizing back to content-box
for your svg containers. Do-able.
As a side note, this obviously isn't how things are supposed to work. Browsers should be smart enough to look at the SVG viewBox attribute to get the proportions, calculate the computedwidth (after any maxWidth limits) and then compute the height.
But it doesn't currently work that way. There's another weird bug in Chrome where adding max-width:100%
to the svg creates a situation where the svg always sizes to the smallest rendered size. Try loading this fiddle in Chrome:
http://jsfiddle.net/ynmey/1/
An you'll see no SVG at all! Weird. Even weirder, toggle off the max-width
declaration in Dev Tools, and then start playing with the width of the "result" viewport in jsfiddle. Take it slightly narrower, then wider, then narrower, then wider. Notice that once the svg gets nudged smaller, it doesn't resize back up again when the viewport gets bigger!
This is important to note because:
* {max-width:100%}
is a common (and totally legit) responsive design approach, and it currently wreaks havoc with SVG in Blink. So stick to intrinsic ratios for now.
The default display type for inline SVG elements is display: inline;
. This means that the SVG element is placed on the typographic baseline of its parent and is aligned accordingly. There is always some space below the baseline to allow for the dangling bits of characters like g and j and such.
Easy fix: svg { display: block;}
or svg { display: inline-block; vertical-align: top; }
.
I'm not entirely sure what effect you're trying to achieve, but I think you might be looking for preserveAspectRatio ="xMinYMin slice"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With