6

I need to embed an svg into html and style it in a responsive way. For regular images this worked nicely for me:

img {
  max-width: 100%;
}

img[height] { 
  height: auto; /* if the <img> tag provides a width keep aspect ratio */
}

unfortunately this doesn't work for embedded svgs. Here is an example how it works for both an embedded svg and a svg within an img tag.

Here is an example markup:

<div>Embedded SVG:
  <svg xmlns="http://www.w3.org/2000/svg" width="300px" height="300px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><circle cx="50" cy="50" r="50" /></svg>
</div>

 <div>SVG as image tag:  
   <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDBweCIgaGVpZ2h0PSIzMDBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjUwIiAvPjwvc3ZnPg0K" />
 </div>

and css:

div {
    resize: both;
    outline: 1px solid red;
    margin-bottom: 3em;
    padding: 1em;
}

svg,
img {
  display: block;
  outline: 1px solid blue;
  max-width: 100%;
  height: auto;
}

scaled down both images preserve aspect their ratio but the embedded svg keeps its original height (the blue outline)

How can I avoid the embedded svg creating a white space?

You can find an example on jsfiddle.

I'd love to post screenshots but I have not enough reputation for that :/

Edit: the bug appears only in chrome. changed the title accordingly

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
loominade
  • 1,028
  • 1
  • 11
  • 21
  • So where do you want the whitespace to be removed from? – XCS Feb 25 '14 at 13:45
  • could easily point it on two screenshots. but stack overflow doesn't allow me to post pictures. Just scale the jsfiddl i posted and you will see the problem – loominade Feb 25 '14 at 13:50
  • I beleive it's as simple as setting the viewport properties of your svg file. At least that's how it works if you use it inside an or an – Marvin Brouwer Feb 25 '14 at 14:55

2 Answers2

12

This isn't technically a Chrome bug, but rather a gap in the SVG specifications. In particular:

Similarly, if there are positioning properties specified on the referencing element or on the outermost svg element that are sufficient to establish the height of the viewport, then these positioning properties establish the viewport's height; otherwise, the ‘height’ attribute on the outermost svg element establishes the viewport's height.

That tells the browser to use the <svg>'s height attribute as the height, unless there is conflicting CSS styles setting a different height, regardless of any consideration of the aspect ratio of the image. Now, most of us would argue that

  • if there is enough information on the <svg> to establish an intrinsic aspect ratio,
  • then any CSS that explicitly defines the width should be considered "positioning properties ... sufficient to establish the height of the viewport".

But the specs never explicitly say that. And while Firefox interprets it that way, Chrome does not.

The non-intuitive solution is to remove the height and width attributes from the <svg> element, use the viewBox attribute to establish the aspect ratio, and use CSS to specify min and max height and width.

<div>
  Embedded SVG:
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" 
       preserveAspectRatio="xMidYMid meet">
     <circle cx="50" cy="50" r="50" />
  </svg>
</div>

CSS:

svg,
img {
  display: block;
  outline: 1px solid blue;
  width:300px;
  max-width: 100%;
  max-height:300px;
  height: auto;
}

http://jsfiddle.net/78cpD/3/

Note that the height:auto; style is required, because the default height style is 100% when you don't specify it as an attribute.

All of which is way simpler than the method I'd been using previously, that involved wrapping the SVG in a <div> and defining a fixed aspect ratio using padding.

Community
  • 1
  • 1
AmeliaBR
  • 27,344
  • 6
  • 86
  • 119
  • This [CSS Tricks](https://css-tricks.com/svg-symbol-good-choice-icons/) post made me think that ``s would solve all our viewbox problems, but this answers shows that's not the case. – Dan Dascalescu Jul 11 '15 at 14:49
  • @DanDascalescu It's getting better. Chrome now is pretty good with auto-sizing, it's Webkit & IE that are the limitations. Symbols, however, have the limitation that they don't filter upwards to cause auto-sizing of the SVG (in any browser). See my comment & demo on that CSS-Tricks post. – AmeliaBR Jul 11 '15 at 22:07
  • This is great, been struggling with this issue and a simple max-width rectified the problem. Thanks @AmeliaBR – Janaki Sathiyamurthy Jul 07 '16 at 10:41
  • I had an issue of excessive white space that was solved just by adding `preserveAspectRatio="xMidYMid meet"` as shown in the answer. – brasofilo Nov 27 '20 at 14:11
0

Someone here came up with a jquery based workaround. that works quite well so far

$(window).bind('resize', function() {
  resizeSvg(context);
});
function resizeSvg(context) {
  $('svg', context).each(function(k,svg) {
    $Svg = $(svg);
    $Svg.removeAttr('style');

    var wantedWidth = parseInt(svg.getAttribute('width'));
    var wantedHeight = parseInt(svg.getAttribute('height'));
    var currentWidth = parseInt($Svg.width());
    var currentHeight = parseInt($Svg.height());
    if (wantedWidth != currentWidth) {
      var ratio = wantedHeight / wantedWidth;
      var newHeight = ratio * currentWidth;
      $Svg.css({'height': newHeight});
    }
  }
}
loominade
  • 1,028
  • 1
  • 11
  • 21