dagda1
dagda1

Reputation: 28800

viewBox attribute with svg height and width attributes set

If you look at this jsbin svg image which has width and height attributes and a viewBox attribute set:

var width = width + margin.left + margin.right;
var height = height + margin.top + margin.bottom;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr('viewBox', '0 0 ' + width + ' ' + height)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

Then the svg does not scale at all.

But if I then comment out the width and height attributes then it does appear to scale like in this bin.

I am very confused by the viewBox attribute, I see lots of examples online with a width, height and viewBox attribute all set. I see the viewBox attribute as negated when there is a width and height attribute.

I am also puzzled by the width and height properties of the viewBox actually correspond to the actual space.

The docs say that you are specifying your own coordinate system but I don't understand what this means and how the width and height correspond to the actual width and height of the document.

Upvotes: 7

Views: 6507

Answers (1)

ccprog
ccprog

Reputation: 21821

tl;dr: viewBox is for drawing whats inside the SVG, width and height tell at what size to display it.

The viewBox defines the canvas and coordinate system you are drawing your SVG into. If it says viewBox="10 50 100 100", and you want to draw a square that covers the upper left quarter of your image, you'll write:

<svg viewBox="10 50 100 100" xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="50" width="50" height="50" />
</svg>

Then, when you want to display your SVG, for example embeded into a html page, width and height tell at what size to display them, just like you would for an image tag:

<div>
  <svg width="250" height="250" viewBox="10 50 100 100"
       xmlns="http://www.w3.org/2000/svg">
    <rect x="10" y="50" width="50" height="50" />
  </svg>
</div>

If your SVG was saved as an external file drawing.svg, you could express the same effect as

<div>
  <img src="drawing.svg" width="250" height="250" />
</div>

In both cases, the square you have drawn would cover the upper left quarter of the image, but since the SVG is drawn at an overall size of 250px ✕ 250px, the square has a side length of 125px ✕ 125px.

In other words, if the width defined in the viewBox is a, and the width defined on the element is b, the effect is the same as scaling everything inside the SVG (horizontally) with a factor of b / a.

(That obviously opens up the question what happens when viewBox height is c, element height is d, and the ratios d / c ≠ b / a don't match? That is what the preserveAspectRatio attribute describes.)

Formally, every combination of width, height, viewBox and preserveAspectRatio can be written equivalently as a transform attribute. The algorithm for this is described here. (Note that for the <svg> element as used here in the example, the x and y attributes must always be 0.)

Upvotes: 5

Related Questions