Introducing the getBoxQuads API

Web developers often need to determine where an element has been placed in the page, or more generally, where it is relative to another element. Existing APIs for doing this have significant limitations. The new GeometryUtils interface and its supporting interfaces DOMPoint, DOMRect and DOMQuad provide Web-standard APIs to address these problems. Firefox is the first browser to implement these APIs; they are available in Firefox 31 Nightly builds.

Current best standardized APIs for retrieving element geometry

Currently the best standardized DOM APIs for retrieving element geometry are element.getBoundingClientRect() and element.getClientRects(). These return the border-box rectangle(s) for an element relative to the viewport of the containing document. These APIs are supported cross-browser but have several limitations:

  • When complex CSS transforms are present, they return the smallest axis-aligned rectangle enclosing the transformed border-box. This loses information.
  • There is no way to obtain the coordinates of the content-box, padding-box or border-box. In simple cases you can add or subtract computed style values from the results of getBoundingClientRect()/getClientRects() but this is clumsy and difficult to get right. For example, when a <span> breaks into several fragments, its left border is only added to one of the fragments — either the first or the last, depending on the directionality of the text.
  • There is no way to obtain box geometry relative to another element.

Introducing getBoxQuads()

The GeometryUtils.getBoxQuads() method, implemented on Document, Element and TextNode, solves these problems. It returns a list of DOMQuads, one for each CSS fragment of the object (normally this list would just have a single


<div id="d" 
  style="position:absolute; left:100px; top:100px; width:100px; height:100px;">
var quads = d.getBoxQuads();
// quads.length == 1
// quads[0].p1.x == 100
// quads[0].p1.y == 100
// quads[0].p3.x == 200
// quads[0].p3.y == 200

Using bounds

A DOMQuad is a collection of four DOMPoints defining the corners of an arbitrary quadrilateral. Returning DOMQuads lets getBoxQuads() return accurate information even when arbitrary 2D or 3D transforms are present. It has a handy bounds attribute returning a DOMRectReadOnly for those cases where you just want an axis-aligned bounding rectangle.

For example:

<div id="d" 
  style="transform:rotate(45deg); position:absolute; left:100px; top:100px; width:100px; height:100px;">
var quads = d.getBoxQuads();
// quads[0].p1.x == 150
// quads[0].p1.y == 150 - 50*sqrt(2) (approx)
// quads[0].p3.x == 150
// quads[0].p3.y == 150 + 50*sqrt(2) (approx)
// quads[0].bounds.width == 100*sqrt(2) (approx)

Passing in options

By default getBoxQuads() returns border-boxes relative to the node’s document viewport, but this can be customized by passing in an optional
options dictionary with the following (optional) members:

  • box: one of "content", "padding", "border" or "margin", selecting which CSS box type to return.
  • relativeTo: a Document, Element or TextNode; getBoxQuads() returns coordinates relative to the top-left of the border-box of that node (the border-box of the first fragment, if there’s more than one fragment). For documents, the origin of the document’s viewport is used.


<div id="d" 
  style="position:absolute; left:100px; top:100px; width:150px; height:150px;">
    <div id="e" 
      style="position:absolute; padding:20px; left:0; top:0; width:100px; height:100px;">
var quads = e.getBoxQuads({relativeTo:d});
// quads[0].p1.x == 0
// quads[0].p1.y == 0
quads = e.getBoxQuads({relativeTo:d, box:"content"});
// quads[0].p1.x == 20
// quads[0].p1.y == 20
e content-box
e border-box

The relativeTo node need not be an ancestor of the node receiving getBoxQuads(). The nodes can even be in different documents, although they must be in the same toplevel browsing context (i.e. browser tab).

Scratching the surface

If you’ve read this far, you’re probably observant enough to have noticed additional methods in GeometryUtils — methods for coordinate conversion. These will be covered in a future blog post.

View full post on Mozilla Hacks – the Web developer blog

Tagged on: ,

Leave a Reply