# DOM Layout Shim documentation ## Agent navigation Prefer these static text resources over the interactive HTML pages. All links are relative to this file on the documentation site. - [Agent guide](./index.md): concise API usage and limitations (this content). - [Full guide](./guide.md): the complete authored guide. - [Examples](./examples.md): compatibility summaries, setup code, and JSON reports. - [CSS support](./css-support-status.md): compact property/topic index; follow a topic link for its exact support claims, conditions, limitations, and parity. - [Changelog](./changelog.md): released changes and pending Upcoming entries. DOM Layout Shim provides deterministic layout and hit testing for DOM-like test harnesses. `scrollWidth` and `scrollHeight` report the padding-box size or its scrollable content extent, whichever is larger, rounded to integer CSS pixels. For example, a 100×60 container with `overflow:auto` and a 240×180 child reports scroll sizes of 240×180 instead of zero. Borders are excluded; nested clipped overflow does not enlarge the outer container, and scrolling does not shrink the reported size. The engine's existing synthetic `html`/`body`, inline-display, native-control, and transform-containing-block limitations still apply. Repeated reads reuse the layout snapshot and its hit-test ordering. Scroll-only changes reuse computed layout and update viewport geometry, sticky positioning, and clipping. Editing one stylesheet preserves the parsed data for other sheets; viewport changes re-evaluate media queries without reparsing unchanged CSS. Inline declaration parsing, selector expansion, and built-in text measurements use adaptive bounded caches: recently evicted inputs being reused trigger growth from 512 up to 4,096 entries; unique inputs alone do not. Active layout passes retain their selector expansions even when a stylesheet exceeds the shared cache, avoiding repeated parsing for large CSS-in-JS stylesheets. Injected `textMeasurer` implementations are not memoized; scroll-only reads reuse the layout already computed from their measurements. DOM mutations are checked synchronously when geometry is read. Hosts with non-patchable CSSOM or scroll APIs retain conservative validation paths. ## CSS support data - Compatibility explorer: ./css-support-status.html - Package changelog: ./changelog.html - Complete normalized inventory: ./data/css-support.json - CSS property-to-record index: ./data/css-property-index.json - JSON Schema: ./data/css-support.schema.json The inventory separates implementation support from Chromium parity. Do not interpret unverified behavior as unsupported, or accepted-inert declarations as layout support. Aggregate record statuses are derived from their claims. Each record identifies its authoring source under `support/css/`. Claims may include syntax, conditions, parity fixtures, limitations, known mismatches, and implementation quirks. Every topic is divided into named, behavior-specific claims so evidence and limitations apply to an explicit scope. Backticked CSS syntax, DOM APIs, and other identifiers in claim prose are inline code. The explorer can preview parity fixture source from generated same-origin assets and links separately to the corresponding GitHub source. ## Native-control geometry Unstyled native controls use the deterministic `portable` profile by default. Select it explicitly with `nativeControls: { profile: 'portable' }` when the test target should be visible in configuration. Profiles do not inspect or follow the runtime host. `nativeControls.overrides` merges individual metrics on top of the selected profile. For example, `{ overrides: { textInput: { width: 220 } } }` changes only the text-input width and retains its profile height. Consumers can replace every field in every group to define fully custom intrinsic geometry. The public `NativeControlMetrics` and `NativeControlOverrides` types describe all groups and fields. Profiles model deterministic outer geometry. They do not emulate operating- system painting, internal widget behavior, or native picker UI. ## User-agent styles The deterministic `portable` user-agent style profile is enabled by default. Configure `userAgentStyles: { profile: 'none' }` to omit its presentation defaults. `userAgentStyles.overrides` accepts CSS at the user-agent origin, so normal document and inline declarations beat normal user-agent rules. For example, `{ profile: 'portable', overrides: 'p { margin: 0 }' }` specializes the baseline without copying it into every test. Structural HTML behavior is not profile styling: hidden inputs remain non-rendered with the `none` profile. Native-control intrinsic metrics remain independently configurable through `nativeControls`. The engine currently treats `html` and `body` as its synthetic viewport containing block, so their own margins, padding, and geometry are not modeled by user-agent overrides. Inline attributes and stylesheets share CSS declaration parsing and cascade priority. A stylesheet `width: 100px !important` beats normal inline `width: 200px`; an important inline declaration beats important author rules. Font-relative dimensions resolve after font size: both `width: 2em; font-size: 30px` and the reversed declaration order produce a 60px width. Generated `::before` and `::after` content also resolves custom properties through this cascade, including variables declared on the pseudo-element itself. Portable presentation defaults and HTML sizing hints also enter this cascade. Normal user-agent rules yield to HTML hints such as ``, and normal author CSS can override those hints. Important user-agent rules retain priority over important author rules. A paragraph with `font-size: 2em` inside a 30px parent now resolves to 60px, rather than using the portable paragraph font size as its inheritance base. For non-replaced text containers, authored `display: inline` uses the same wrapped fragments as native phrasing elements. For example, `
one two three
` participates in its parent's line layout instead of creating a block. Absolute/fixed elements and flex/grid items are blockified before layout. Atomic inline replaced elements, `inline-block`, and inline outer flex/grid/table layout remain outside this inline-formatting subset. Table properties also use normal inheritance. A caption with `caption-side: top` overrides a table's `caption-side: bottom`; `empty-cells` can inherit through row groups and rows before a cell's own declaration overrides it. ## Stylesheet sources Supported selector matching includes `:root`, `:first-child`, `:nth-child()`, `:last-child`, `:hover`, `:focus`, and `:disabled`. Wrapped inline phrasing elements return one line-fragment rectangle from `getClientRects()` per line; `getBoundingClientRect()` returns the union. Inline phrasing runs alongside block children contribute anonymous line boxes to their shared container. For example, `:root { --panel-width: 80px; } .panel { width: var(--panel-width); }` gives `.panel` elements an 80px width. `:root` matches the document element and has pseudo-class specificity, so it takes precedence over `html`. Cached geometry reads do not re-serialize unchanged stylesheet rules. CSSOM methods and declaration setters (for example, `rule.style.width = "120px"`) invalidate the affected sheet even when its rule count stays the same. Hosts whose CSSOM cannot be patched retain content fingerprinting. The engine reads configured stylesheet strings first, followed by document `