Andreas Mueller
Andreas Mueller

Reputation: 241

Whats the correct way to get the bounding box of DOM elements containing svg

I have the following html and get strange results with getBoundingClientRect, if there are svg elements inside:

<html>
<head>
  <meta charset="utf-8">
  <title>Test</title>
</head>
<body>
<svg>
<g transform="translate(10,10) scale(1)">
  <g class="nodes">
    <g style="inline" transform="translate(20,20)">
      <rect style="stroke: rgb(170, 170, 170); stroke-width: 1; fill: rgb(248, 248, 248);" width="100" height="90"></rect>
      <g class="nodeparent">
        <rect class="noderect" style="fill: none; stroke: rgb(182, 204, 216); stroke-width: 0;" x="0" y="0" height="20" width="100"></rect>
        <text class="nodetext" x="3" y="15">Text 1</text>
      </g>
      <g class="nodeparent">
        <rect class="noderect" style="fill: none; stroke: rgb(221, 185, 172); stroke-width: 0;" x="0" y="22" height="20" width="100"></rect>
        <text class="nodetext" x="3" y="37">Test 2</text>
      </g>
      <g class="nodeparent">
        <rect class="noderect" style="fill: none; stroke: rgb(221, 185, 180); stroke-width: 0;" x="0" y="44" height="20" width="100"></rect>
        <text class="nodetext" x="3" y="59">Test 3</text>
      </g>
      <g class="nodebox">
        <rect class="noderect" style="fill: rgb(236, 163, 154); stroke: rgb(212, 139, 130); stroke-width: 2;" x="0" y="66" height="20" width="100"></rect>
        <text class="nodetext" x="3" y="81">Test 4</text>
        <g class="nodeicon">
          <svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" x="80" y="68">
            <rect height="14" width="14" y="1" x="1" stroke="#888888" stroke-width="1" fill="#ffffff" fill-opacity="0.5"></rect>
            <line x1="4" y1="8" x2="12" y2="8" stroke="#888888" stroke-width="2"></line>
          </svg>
        </g>
      </g>
    </g>
  </g>
</g>
</svg>
</body>
</html>

I get a much greater rectangle than I would expect in Firefox. When I inspect the objects, the displayed bounding box for the inner svg element is fine, but the surrounding g element (class nodeicon) is outside. If I remove this g element, the next surrounding g element is outside. The following picture shows this:

Image showing the problem

It looks like the offset of the svg is applied twice.

Is getBoundingClientRect the correct way to get the position and size of elements (e.g. the g element with class nodes) for this? Is there something wrong with the HTML or svg element or did I run into a Firefox bug?

I am using the current version of Firefox (58.0 64bit).

Upvotes: 2

Views: 472

Answers (1)

Perran Mitchell
Perran Mitchell

Reputation: 1158

A problem that you have here is that the svg tag nested inside the g tag (.nodeicon) is starting a new viewport context. Strictly speaking it should not be nested inside a g tag anyway, but regardless, it isn't really necessary as you're using it as a method of grouping the two elements inside it - which is the purpose of the g tag.

Try removing the svg tag nested inside .nodeicon, and move the coordinates in that svg's x and y attributes to a transform attribute on the g tag.

i.e:

<g class="nodeicon" transform="translate(80, 68)"> <rect height="14" width="14" y="1" x="1" stroke="#888888" stroke-width="1" fill="#ffffff" fill-opacity="0.5"></rect> <line x1="4" y1="8" x2="12" y2="8" stroke="#888888" stroke-width="2"></line> </g>

Upvotes: 1

Related Questions