Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Responsive INLINE SVG - content of svg must fill parent width

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.

  • The inner content of svg doesn't always fill the svg element in all screen widths
  • webkit adds a mysterious padding/height (in this example the padding is within svg element) The height of SVG element should be auto and wrap the inner svg content.

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> 
like image 286
Timidfriendly Avatar asked May 29 '13 12:05

Timidfriendly


People also ask

How do I make SVG fit to the parent container 100?

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.

Can you make an SVG responsive?

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.

How do I make SVG Scalable?

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.

How do I scale SVG viewBox?

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


3 Answers

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.

like image 174
Ben Avatar answered Oct 23 '22 06:10

Ben


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; }.

like image 43
jvhellemond Avatar answered Oct 23 '22 04:10

jvhellemond


I'm not entirely sure what effect you're trying to achieve, but I think you might be looking for preserveAspectRatio ="xMinYMin slice"

like image 3
Michael Mullany Avatar answered Oct 23 '22 05:10

Michael Mullany