5

I like to react to changes of the size of an SVG element in an HTML document. After some research, I found the ResizeObserver API that is intended for listening for such changes regarding a given HTML or SVG element (stackoverflow, MDN). Unfortunately, I couldn't make it work for the SVG element.

My example contains a DIV element, an SVG element and for each of them a ResizeObserver:

const svg = document.querySelector('#svg')
const svgInfo = document.querySelector('#svg-info')
const div = document.querySelector('#div')
const divInfo = document.querySelector('#div-info')

const svgObserver = new ResizeObserver(() => {
  svgInfo.textContent = svg.clientWidth
})
svgObserver.observe(svg)
const divObserver = new ResizeObserver(() => {
  divInfo.textContent = div.clientWidth
})
divObserver.observe(div)
<svg id="svg" style="background-color: red; width: 100%; height: 50px"></svg>
<div id="svg-info">initial</div>
<div id="div" style="background-color: blue; width: 100%; height: 50px"></div>
<div id="div-info">initial</div>

I expect that both ResizeObservers trigger when resizing the elements, e.g., by resizing the window. This would be visible due to changes of both info labels. Yet, for me (Mozilla Firefox 84.0), only the info label for the DIV element changes.

As a workaround, I can think of wrapping my SVG with a DIV as a proxy. Nevertheless, I still wonder why the combination of ResizeObserver and SVG does not work.

Thomas
  • 53
  • 5
  • 4
    From what i can tell from reading the spec, SVG's aren't currently observable, though the intent is there for them to be. this is due to a technical reason, as they use a bounding box, rather than content box. thus ResizeObserver is not able to observe the changes and fire events. This is a current limitation they are working on. I do not know if there is any available workaround or not. – r3wt Jan 04 '21 at 15:26
  • As of writing, Chromium browsers alone now seem to push ResizeObserver updates on content box changes. Other engines still don't, and worse yet, if you rely on their ResizeObserverEntry arguments, the 'update' will give you bounding box values for contentRect -- confusing! I'd recommend Krischna's solution of relying on a containing element for now... – tdhsmith May 26 '23 at 15:36

1 Answers1

1

You will have to wrap the SVG inside a DIV element an observe the the wrapping DIV element, like so:

const svg = document.querySelector('#svg')
const svgInfo = document.querySelector('#svg-info')
const div = document.querySelector('#div')
const divInfo = document.querySelector('#div-info')

const svgObserver = new ResizeObserver(() => {
  svgInfo.textContent = svg.clientWidth
})
svgObserver.observe(svg)
const divObserver = new ResizeObserver(() => {
  divInfo.textContent = div.clientWidth
})
divObserver.observe(div)
<div id="svg" style="background-color: red; width: 100%; height: 50px">
    <svg style="width: 100%; height: 100%"></svg>
</div>
<div id="svg-info">initial</div>
<div id="div" style="background-color: blue; width: 100%; height: 50px"></div>
<div id="div-info">initial</div>