The web platform has always been excellent at laying things out, but surprisingly reluctant to tell us the exact geometry it produced. That becomes a problem the moment an interface needs to draw on top of the page instead of merely living inside it.

Consider a visual editor. The selected component might sit inside three transformed ancestors, a scrolled container and an iframe. To draw a precise outline, resize handles or a connector, the editor needs the component’s real corners in a coordinate space it controls. An axis-aligned rectangle is no longer enough.

Approximation

getBoundingClientRect()

Returns x, y, width and height for the smallest viewport-aligned rectangle around the result.

Actual geometry

getBoxQuads()

Returns four ordered DOMPoints for each CSS fragment, preserving rotation, skew, transforms and the chosen box edge.

01

One method, four honest corners

getBoxQuads() is part of the CSSOM View GeometryUtils interface. Call it on an Element, Text node or Document. It returns an array because one node can produce multiple fragments—for example, inline text wrapping across lines.

selection-overlay.js
const [quad] = selectedElement.getBoxQuads({
  box: "border",
  relativeTo: overlayLayer,
});

const corners = [quad.p1, quad.p2, quad.p3, quad.p4];
overlayPath.setAttribute(
  "points",
  corners.map(({ x, y }) => `${x},${y}`).join(" ")
);
p1top left
p2top right
p3bottom right
p4bottom left

The box option chooses margin, border, padding or content. The relativeTo option is the quiet superpower: it asks the browser to express those points directly in another node’s coordinate system.

02 · live example

A selection overlay that stays attached

Change the selected card’s layout state. The orange outline is not a CSS border—it is an SVG polygon drawn from the four points returned by getBoxQuads().

p1 0, 0

Campaign / Summer

Build beyond
the rectangle.
Geometry that follows the design.
See the essential code
const [quad] = card.getBoxQuads({
  box: "border",
  relativeTo: canvas,
});

drawSelection([quad.p1, quad.p2, quad.p3, quad.p4]);

03

Coordinate conversion, without matrix archaeology

The rest of GeometryUtils solves the inverse problem: you already have a point, rectangle or quad, but it belongs to the wrong node. The conversion methods move that geometry from one local coordinate system into another while accounting for the transforms between them.

  • convertPointFromNode()Map a cursor, anchor or handle.
  • convertRectFromNode()Move a rectangular region between nodes.
  • convertQuadFromNode()Preserve all four corners across spaces.
convertPointFromNode() local (140, 110) → workbench (0, 0)
1Click local coordinates
local x 140 · y 110
2Click transformed space
workbench x 0 · y 0
Click either grid. The API projects local coordinates onto the transformed element and converts transformed clicks back into local coordinates.
point-conversion.js
// local → workbench: place the transformed marker
const pointOnWorkbench = workbench.convertPointFromNode(
  localPoint,
  transformedSpace,
);

// workbench → local: handle a click on the transformed grid
const localPoint = transformedSpace.convertPointFromNode(
  clickOnWorkbench,
  workbench,
);

04

Where precise DOM geometry earns its keep

This is not only a low-level browser curiosity. It is the missing primitive behind a broad family of interfaces that must understand the page visually.

01

Visual editors

Selection outlines, resize handles, snapping guides and drop zones on transformed components.

02

Diagramming

Connectors that meet the actual edge of a node instead of its viewport-aligned bounding box.

03

Inspection tools

Devtools overlays, measurement labels and geometry visualizers that agree with what users see.

04

Export pipelines

Accurate DOM-to-vector conversion for PDF, SVG, DXF and other geometry-first formats.

Already used in practice

05

Using it today

Until native implementations are consistently enabled across engines, feature detection plus a polyfill is the pragmatic route. The polyfill adds the GeometryUtils methods to Node and keeps application code close to the standard API.

npm
npm install get-box-quads-polyfill

import { addPolyfill } from "get-box-quads-polyfill";

if (!("getBoxQuads" in Element.prototype)) {
  addPolyfill(window);
}

const quads = element.getBoxQuads({
  box: "border",
  relativeTo: document.body,
});

A polyfill can reconstruct only the geometry JavaScript is allowed to observe. This one focuses on HTML and has limited SVG and MathML support because some nodes do not expose layout properties such as offsetLeft and offsetTop. Shadow DOM adds similar hard boundaries: open roots and common slotting cases can be handled, but closed or otherwise inaccessible trees—and browser-internal layout details across those boundaries— cannot be recovered reliably from page script. Those are platform limitations, not missing matrix math. For repeated measurements the polyfill also provides an optional cache; clear it whenever layout changes.

06 · ecosystem update

The engines are catching up

The interesting story in 2026 is no longer whether this API is implementable. Multiple engines now have working implementations; the remaining work is review, performance, interoperability and the decision to expose it broadly.

Firefox

Mozilla has long had a native implementation. Public exposure has historically been preference-gated, and those preferences were switched off again in Nightly in 2026 while cross-engine interest develops.

Status ↗

Chrome / Chromium

The GeometryUtils implementation landed in Chromium in August 2026. It is currently available behind Chrome’s “Experimental Web Platform features” flag.

Safari / WebKit

A draft WebKit pull request implements GeometryUtils for Document, Element and Text, with CSS box selection and relative coordinate spaces.

WebKit PR #71448 ↗

Ladybird

There is also a working LibWeb implementation covering the same core GeometryUtils surface—a useful sign that the model transfers beyond the established engines.

Implementation ↗

07

A small API with a large surface area

getBoxQuads() does one humble thing: it exposes geometry the browser has already calculated. But that honest set of points unlocks editors, overlays, inspectors, export tools and interactions that otherwise require brittle walks through CSS transforms.

The four corners were always there. The web platform is finally giving them names.