John
John

Reputation: 3115

GetBoundingClientRect but relative to the entire document

Is there a method for getting the client rect for an element relative to the document besides offset? getBoundingClientRect() gets the value relative to the client's browser.

I'm using D3 and jQuery's height() nor width() are working (I've even tried doing it window.load()), but offset() is. Neither are javascripts .offset

return [$e.offset().top + $e.height()/2, $e.offset().left + $e.width()/2]

$e.height() and $e.width() both return 0

It's an SVG element, I'm just using it to edit my SVG. It's much easier to load/handle SVG's with D3. The project is not data related, it's just a map.

Upvotes: 30

Views: 21253

Answers (2)

Lucidity
Lucidity

Reputation: 1369

Here's an ES6 method that returns all the same properties as getBoundingClientRect() but relative to the entire document.

const getOffsetRect = (el) =>

  let rect   = el.getBoundingClientRect();

  // add window scroll position to get the offset position
  let left   = rect.left   + window.scrollX;
  let top    = rect.top    + window.scrollY;
  let right  = rect.right  + window.scrollX;
  let bottom = rect.bottom + window.scrollY;

  // polyfill missing 'x' and 'y' rect properties not returned
  // from getBoundingClientRect() by older browsers
  let x = rect.x === undefined ? left : rect.x + window.scrollX;
  let y = rect.y === undefined ? top : rect.y + window.scrollY;

  // width and height are the same
  let width  = rect.width;
  let height = rect.height;

  return { left, top, right, bottom, x, y, width, height };
};

Note: it's also poly-filling the x and y props, that are not returned from getBoundingClientRect() by older browsers

Upvotes: 11

Ian Storm Taylor
Ian Storm Taylor

Reputation: 8690

Using element.getBoundingClientRect() by itself returns top and left values that are relative to the viewport, like you discovered. If you want them to be relative to the document (and not be affected by scroll position), you can add the scroll position using window.scrollY and window.scrollX, like so:

const rect = element.getBoundingClientRect()

rect.left                   // (relative to viewport)
rect.top                    // (relative to viewport)
rect.left + window.scrollX  // (relative to document)
rect.top + window.scrollY   // (relative to document)

Source.

Upvotes: 32

Related Questions