Making dynamic SVG content fit

One of the most useful things about SVGs is being able to dynamically change its contents at any time. The problem is, the SVG frame doesn't care if the contents change.

Let's start with this:

<svg viewBox="0 0 100 100" width="150" height="150">
  <circle cx="50" cy="50" r="50"></circle>
</svg>

We have a circle that neatly fills the frame.

Now, what about when an SVG contains content that spills out of the viewBox?

We can use a little Javascript to get the viewBox to make sure everything in the SVG is visible.

function makeFit(svg, targetContent) {
  let content = targetContent.getBBox(); 

  // Get dimensions of target content
  const posX = content.x;
  const posY = content.y;
  const width = content.width;
  const height = content.height;

  // Generate new viewBox values
  const newViewBox = `${posX} ${posY} ${width} ${height}`;

  // Apply them to the SVG  
  svg.setAttribute('viewBox', newViewBox);
}

We pass in the SVG element (so we know where the viewBox is), and the element inside that we want to focus on.

The function finds the content, gets its position within the SVG and then updates the viewBox with that position.

Because SVGs are awesome, this will even effectively zoom in or out if the size of the content has changed.

You could also focus on different bits of content if you wanted, or animate it however you like.