getBBox() vs getBoundingClientRect() vs getClientRects()

JavascriptDomSvg

Javascript Problem Overview


I am unable to find an explicit reference for the use of these functions: getBBox() vs getBoundingClientRect() vs getClientRects().

Could you explain what they do and what are the coordinates (and their referential) they return?

Javascript Solutions


Solution 1 - Javascript

getBBox is defined in the SVG specification it returns coordinates in the local coordinate system after the application of transforms.

getBoundingClientRect and getClientRects are defined in the CSSOM specification. Their main difference is that they return coordinates in the outer SVG coordinate system.

getBoundingClientRect returns a single rect that is the union of all the rects that getClientRect would return.

Solution 2 - Javascript

some elements(like span tag) will have multiple ClientRects when they are wrapped into multiple lines.MDN Element.getClientRects()
and a BoundingRect is the union of ClientRects of a element.MDN Element.getBoundingClientRect()

Solution 3 - Javascript

This is an example I copied from MDN Element.getClientRects() and I added addBoundingClientRectOverlay function to compare addClientRectsOverlay. You can see the red rectangle is from getClientRects and the black dash rectangle is from getBoundingClientRect, so you can tell what's different. enter image description here

function addClientRectsOverlay(elt) {
  // Absolutely position a div over each client rect so that its border width
  // is the same as the rectangle's width.
  // Note: the overlays will be out of place if the user resizes or zooms.
  var rects = elt.getClientRects();

  for (var i = 0; i != rects.length; i++) {
    var rect = rects[i];
    var tableRectDiv = document.createElement("div");
    tableRectDiv.style.position = "absolute";
    tableRectDiv.style.border = "1px solid red";
    var scrollTop =
      document.documentElement.scrollTop || document.body.scrollTop;
    var scrollLeft =
      document.documentElement.scrollLeft || document.body.scrollLeft;
    tableRectDiv.style.margin = tableRectDiv.style.padding = "0";
    tableRectDiv.style.top = rect.top + scrollTop + "px";
    tableRectDiv.style.left = rect.left + scrollLeft + "px"; // we want rect.width to be the border width, so content width is 2px less.
    tableRectDiv.style.width = rect.width - 2 + "px";
    tableRectDiv.style.height = rect.height - 2 + "px";
    document.body.appendChild(tableRectDiv);
  }
}
function addBoundingClientRectOverlay(elt) {
  // Absolutely position a div over each client rect so that its border width
  // is the same as the rectangle's width.
  // Note: the overlays will be out of place if the user resizes or zooms.
  var rect = elt.getBoundingClientRect();

  var tableRectDiv = document.createElement("div");
  tableRectDiv.style.position = "absolute";
  tableRectDiv.style.border = "1px dashed #321";
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  var scrollLeft =
    document.documentElement.scrollLeft || document.body.scrollLeft;
  tableRectDiv.style.margin = tableRectDiv.style.padding = "0";
  tableRectDiv.style.top = rect.top + scrollTop+1 + "px";
  tableRectDiv.style.left = rect.left + scrollLeft+1 + "px"; // we want rect.width to be the border width, so content width is 2px less.
  tableRectDiv.style.width = rect.width - 4 + "px";
  tableRectDiv.style.height = rect.height - 4 + "px";
  document.body.appendChild(tableRectDiv);
}
(function() {
  /* call function addClientRectsOverlay(elt) for all elements with assigned css class "withClientRectsOverlay"  */
  var elt = document.getElementsByClassName("withClientRectsOverlay");
  for (var i = 0; i < elt.length; i++) {
    addClientRectsOverlay(elt[i]);
    addBoundingClientRectOverlay(elt[i]);
  }
})();

strong {
  text-align: center;
}
div {
  display: inline-block;
  width: 150px;
}
div p,
ol,
table {
  border: 1px solid blue;
}
span,
li,
th,
td {
  border: 1px solid green;
}

<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects -->

<h3>A paragraph with a span inside</h3>
<p>Both the span and the paragraph have a border set. The client rects are in red. Note that the p has only one border box, while the span has multiple border boxes.</p>

<div>
 <strong>Original</strong>
 <p>
  <span>Paragraph that spans multiple lines</span>
 </p>
</div>
 
<div>
 <strong>p's rect</strong>
 <p class="withClientRectsOverlay">
  <span>Paragraph that spans multiple lines</span>
 </p>
</div>

<div>
 <strong>span's rect</strong>
 <p>
  <span class="withClientRectsOverlay">Paragraph that spans multiple lines</span>
 </p>
</div><h3>A list</h3>
<p>Note that the border box doesn't include the number, so neither do the client rects.</p>

<div>
 <strong>Original</strong>
 <ol>
  <li>Item 1</li>
  <li>Item 2</li>
 </ol>
</div>

<div>
 <strong>ol's rect</strong>
 <ol class="withClientRectsOverlay">
  <li>Item 1</li>
  <li>Item 2</li>
 </ol>
</div>

<div>
 <strong>each li's rect</strong>
 <ol>
  <li class="withClientRectsOverlay">Item 1</li>
  <li class="withClientRectsOverlay">Item 2</li>
 </ol>
</div><h3>A table with a caption</h3>
<p>Although the table's border box doesn't include the caption, the client rects do include the caption.</p>

<div>
 <strong>Original</strong>
 <table>
  <caption>caption</caption>
  <thead>
    <tr><th>thead</th></tr>
  </thead>
  <tbody>
    <tr><td>tbody</td></tr>
  </tbody>
 </table>
</div>
 
<div>
 <strong>table's rect</strong>
 <table class="withClientRectsOverlay">
  <caption>caption</caption>
  <thead>
    <tr><th>thead</th></tr>
  </thead>
  <tbody>
    <tr><td>tbody</td></tr>
  </tbody>
 </table>
</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTroopersView Question on Stackoverflow
Solution 1 - JavascriptRobert LongsonView Answer on Stackoverflow
Solution 2 - JavascriptwangkaibuleView Answer on Stackoverflow
Solution 3 - JavascriptfoxirisView Answer on Stackoverflow