Problem
Since 3af7403 (0.1.11) getComputedStyle() resolves the cascade, so a stylesheet rule reaches it. getBoundingClientRect() was not brought along, and still reads inline styles only. The two APIs now disagree about the same element.
import { GlobalRegistrator } from 'very-happy-dom'
GlobalRegistrator.register()
document.head.innerHTML = '<style>.box { width: 120px; height: 40px }</style>'
document.body.innerHTML = '<div class="box" id="a">a</div>'
const el = document.getElementById('a')!
getComputedStyle(el).getPropertyValue('width') // "120px" ✅ cascade applied
el.getBoundingClientRect() // { width: 0, height: 0 } ❌Setting style="width: 120px" inline gives a rect of 120. Only the cascade path is missing.
Why it matters
This is the failure mode the testing guidance warns about, arriving through a new door. Someone confirms getComputedStyle reports the class-based width, reasonably concludes styles are wired up, and writes a geometry assertion. It compares 0 to 0 and passes while checking nothing.
Before 0.1.11 the guidance was simple — no cascade, no layout, keep geometry out. Now the line runs between two APIs that look equally live, and the one that silently answers 0 is the one people reach for when asserting size.
It is also what makes size-touching specs unportable. Twelve of twelve Playwright specs surveyed in a downstream app could not move here, and element geometry was one of the four structural blockers.
Proposed scope
Have the box metrics read the same resolved style getComputedStyle() already computes:
getBoundingClientRect()—width/heightfrom the cascade, keeping the origin at0, 0offsetWidth/offsetHeight,clientWidth/clientHeight— the same, with border and padding accounted for as they are today for inline styles
That is a box-metrics fix, not a layout engine.
Explicitly out of scope, and should stay documented as absent: normal flow, positioning, stacking and overlap, scroll offsets, percentage or viewport-relative units that need a containing block, and anything requiring paint. x/y/top/left stay 0.
Acceptance
- An element sized only by a stylesheet reports that size from
getBoundingClientRect(),offsetWidth/offsetHeightandclientWidth/clientHeight. - Specificity,
!importantand inline-over-stylesheet precedence decide the winner, exactly asgetComputedStyle()already decides it. - An element with no width from any source still reports
0, and the docs still say geometry beyond explicit sizes is not computed. - A test asserts the two APIs agree, so they cannot drift apart again.
Note
stacksjs/stacks docs/guide/testing.md has been corrected to describe the post-0.1.11 behaviour and to name this specific mismatch, so the trap is at least written down while this is open.