CSS Typed Object Model
For as long as CSS has existed, JavaScript has read and written it as plain strings: el.style.width = "20px", then parsed whatever came back from getComputedStyle by hand. The CSS Typed Object Model (Typed OM) replaces those strings with real typed JavaScript objects — numbers with attached units, not text you have to re-parse every time you touch it.
The problem with string-based styles
el.style.width = '100px'; const width = getComputedStyle(el).width; // "100px" — a string const num = parseFloat(width) + 10; // manual parsing to do math el.style.width = num + 'px'; // manual re-stringifying
Every read is a string that must be parsed (with a manual parseFloat), and every write must be a correctly formatted string, including the unit — an easy source of subtle bugs (forgetting the px, mixing up units) and unnecessary parsing overhead when this happens inside a hot animation loop.
attributeStyleMap — typed, structured access
el.attributeStyleMap.set('width', CSS.px(120));
el.attributeStyleMap.set('opacity', 0.5);
const width = el.attributeStyleMap.get('width');
console.log(width.value, width.unit); // 120 "px" — already parsed for youel.attributeStyleMapis the typed equivalent ofel.style— same idea (the element's own inline style), but every value is a structured object instead of a raw string.CSS.px(120),CSS.percent(50),CSS.deg(45)are factory functions that build a typed value with its unit already attached, instead of you concatenating a string.Reading a value back gives you a
CSSUnitValueobject —.valueand.unitare already split apart, noparseFloat/regex needed.
CSSUnitValue — numbers with units, and arithmetic
const a = CSS.px(10);
const b = CSS.px(5);
const sum = a.add(b); // CSSUnitValue { value: 15, unit: "px" }
const scaled = a.mul(2); // CSSUnitValue { value: 20, unit: "px" }
// Mixed units build a CSSMathSum instead of failing silently
const mixed = CSS.px(10).add(CSS.percent(5)); // calc(10px + 5%), kept symbolicpx and %) does not throw or silently coerce — it produces a CSSMathSum, the typed equivalent of a CSS calc() expression, preserving both operands until the browser actually needs to resolve a final pixel value.computedStyleMap() — typed reads of computed styles
const styleMap = el.computedStyleMap();
const fontSize = styleMap.get('font-size'); // CSSUnitValue, e.g. { value: 16, unit: "px" }
const display = styleMap.get('display'); // CSSKeywordValue { value: "flex" }computedStyleMap() is the typed replacement for getComputedStyle() — instead of a CSSStyleDeclaration full of strings, every property resolves to the appropriate typed value class: CSSUnitValue for dimensions, CSSKeywordValue for keywords like flex or none, CSSColorValue for colors, and so on.
Numeric values without string parsing
The headline benefit is doing repeated layout math — dragging an element, driving a custom scrubber, running a physics-based animation — without a parse/stringify round trip on every single frame.
function onDrag(el, deltaX) {
const current = el.attributeStyleMap.get('translate') ?? CSS.px(0);
const next = current.add(CSS.px(deltaX));
el.attributeStyleMap.set('translate', next);
// No string concatenation, no parseFloat, on every mousemove frame
}Use with Houdini
Typed OM is one pillar of the broader CSS Houdini project (see the CSS Houdini Overview page) — the same typed values are what get passed into a registered @property custom property, and into a Paint Worklet's style map, rather than raw strings. If you register a custom property with @property and a numeric syntax (<number>, <length>), reading it back through Typed OM gives you a proper typed value instead of text.
Performance benefit, honestly assessed
Scenario | String-based style API | Typed OM |
|---|---|---|
One-off style change | Negligible difference | Negligible difference |
High-frequency updates (drag, scroll-linked animation) | Parse/stringify cost repeats every frame | Values stay structured; avoids redundant parsing |
Reading many computed values at once | Each is a separate string to parse | Each is already the correct typed object |
el.style everywhere.Browser support
Typed OM shipped in Chromium-based browsers first and has broader but not universal support — check current status before depending on it for anything outside a progressive enhancement. el.style and getComputedStyle() remain fully supported everywhere and are the correct fallback.
Related pages: CSS Houdini Overview, CSS Paint API (Houdini), @property — typed custom properties, and calc().