0

I am trying to achieve an outcome where an <svg> element has the same viewBox dimensions as the <div> it is contained within. For example:

<div style="width:100%; height:100%">
  <svg viewBox="0 0 ?? ??"></svg>
</div>

My div is designed to fill its available space in the layout (in reality, it's not using "100%", but rather a flex:1 in a flexbox, but the behavior I'm observing is the same)

To achieve this, I am programmatically setting the viewBox to the values of the containing div. For example:

svg.setAttribute('viewBox', `0 0 ${div.clientWidth} ${div.clientHeight}`);

OK cool, however the problem is that the act of setting the viewBox changes the dimensions of the container div (um.. wut?)

I have toiled with all manner of padding:0px (etc) options on all elements, but no dice. The side effect of this is an ever-growing viewBox as every time there is an event that causes the container div to change dimensions (like a window resize), the viewBox is updated, which in-turn increases the size of the container div. See the sample:

const setViewBoxToDivDimensions = () => {
  let svg = document.getElementById('mySvg');
  // Set the viewBox of the SVG to the dimensions of the container div
  svg.setAttribute('viewBox', `0 0 ${container.clientWidth} ${container.clientHeight}`);
  // Display the resulting values
  getAndDisplayVals();
}

const getAndDisplayVals = () => {
  let container = document.getElementById('container');
  let svg = document.getElementById('mySvg');  
  
  let dimsResult = `Dimensions of container DIV are: ${container.clientWidth} x ${container.clientHeight}`;
  let vbResult = `viewBox of SVG is: ${svg.getAttribute('viewBox')}`;  
  document.getElementById('dimsResult').innerHTML = dimsResult;
  document.getElementById('vbResult').innerHTML = vbResult;
}

document.getElementById('setViewBox').addEventListener('click', e => {
  setViewBoxToDivDimensions();
});

window.addEventListener('resize', e => {
  setViewBoxToDivDimensions();
  getAndDisplayVals();
});

getAndDisplayVals();
Clicking the button, or resizing the window, will cause the viewBox to be updated with the dimensions of the "container" DIV. This will actually cause the DIV to grow :/
<p/>
<button id="setViewBox">Change viewBox</button>
<p/>
<div id="vbResult"></div>
<div id="dimsResult"></div>
<div id="container" style="padding:0px; margin:0px">
  <svg id="mySvg" viewBox="0 0 100 100" style="background-color:grey;padding:0px; margin:0px"></svg>
</div>
Jason Polites
  • 5,571
  • 3
  • 25
  • 24

1 Answers1

2

This issue will no longer occur when the display: block css attribute is applied to the SVG element.

This is because without this attribute the container will have a very slightly higher height than the SVG, due to display: inline being the default for SVG elements. See Why does inline-block cause this div to have height? for detail about why this display property causes additional height.

Peter Warrington
  • 654
  • 10
  • 32