Podcast
Link to the Podcast
Notes
CSS Typed Object Model (Typed OM)
CSS Typed OM API allow manipulating CSS styles through a typed JS representation rather than a simple string.
Provide performance win. Browser understands the structured JS representation and no longer needs to parse CSS string from scratch.
const div = document . createElement ( ' div ' );
// browser needs to parse the string to understand and use it
div . style . height = ' 5px ' ;
// browser understands and use the value as 5px
div . style . height = CSS . px ( 5 );
Enter fullscreen mode
Exit fullscreen mode
Built-in error handling. You can't provide invalid value to a type.
div . attributeStyleMap . set ( ' color ' , CSS . px ( 10 ))
// TypeError: Failed to set, invalid type for property
Enter fullscreen mode
Exit fullscreen mode
Rather than manipulating raw string, developer can create / transform CSS in a meaningful object
const _5px = CSS . px ( 5 ); // 5px
const _15px = _5px . add ( CSS . px ( 10 )); // 15px;
const div = document . createElement ( ' div ' );
div . style . height = _15px ;
// <div style="height: 15px;"></div>
Enter fullscreen mode
Exit fullscreen mode
API based on functional programming concept
To check browser support Typed OM, currently (21 Nov 2020) supported in Safari Tech Preview & Chromium
// checking browser support
if ( window . CSS && CSS . number ) {
// 😍 browser supports Typed OM!
}
Enter fullscreen mode
Exit fullscreen mode
computedStyleMap
<script>
const element = document . querySelector ( ' #app ' );
console . log ( element . computedStyleMap (). get ( ' font-size ' ));
// Specification: CSSUnitValue { value: 2, unit: 'rem' }
// Chrome: CSSUnitValue { value: 32, unit: 'px' }
console . log ( window . getComputedStyle ( element ). fontSize );
// "32px"
</script>
<div id= "app" style= "font-size: 2rem;" ></div>
Enter fullscreen mode
Exit fullscreen mode
attributeStyleMap
parse, modify inline styles
<script>
const element = document . querySelector ( ' #app ' );
const inlineStyles = element . attributeStyleMap ;
console . log ( inlineStyles . get ( ' font-size ' ));
// CSSUnitValue { value: 2, unit: 'rem' }
inlineStyles . set ( ' height ' , CSS . px ( 10 ));
// < div id = " app " style = " font-size: 2rem; height: 10px; " >< /div >
inlineStyles . clear ();
// < div id = " app " style = "" >< /div >
inlineStyles . append ( ' background-image ' , ' linear-gradient(yellow, green) ' );
inlineStyles . append ( ' background-image ' , ' linear-gradient(to bottom, blue, red) ' );
// < div id = " app "
// style="background-image: linear-gradient(yellow, green),
// linear-gradient(to bottom, blue, red)"> < /div >
inlineStyles . delete ( ' background ' );
// < div id = " app " style = "" >< /div >
inlineStyles . has ( ' opacity ' );
// false
</script>
<div id= "app" style= "font-size: 2rem;" ></div>
Enter fullscreen mode
Exit fullscreen mode
<script>
// `attributeStyleMap` only gets inline style
console . log ( element . attributeStyleMap . get ( ' color ' ));
// null
console . log ( element . computedStyleMap (). get ( ' color ' ));
// CSSStyleValue { /* red */ }
</script>
<div id= "app" style= "font-size: 2rem;" ></div>
<style>
#app {
color : red ;
}
</style>
Enter fullscreen mode
Exit fullscreen mode
Types of CSSStyleValue
CSSImageValue
CSSKeywordValue
CSSNumericValue
CSSPositionValue
CSSTransformValue
CSSUnparsedValue
create CSSStyleValue
CSSStyleValue . parse ( ' font-size ' , ' 32px ' );
// CSSUnitValue { value: 2, unit: 'px' }
CSSStyleValue . parse ( ' transform ' , ' translate3d(10px, 20px, 30px) scale(1.5) ' );
/*
CSSTransformValue {
0: CSSTranslate {
is2D: false
x: CSSUnitValue { value: 10, unit: 'px' }
y: CSSUnitValue { value: 20, unit: 'px' }
z: CSSUnitValue { value: 30, unit: 'px' }
}
1: CSSScale {
is2D: true
x: CSSUnitValue { value: 1.5, unit: 'number' }
y: CSSUnitValue { value: 1.5, unit: 'number' }
z: CSSUnitValue { value: 1, unit: 'number' }
}
}
*/
Enter fullscreen mode
Exit fullscreen mode
CSSImageValue
does not cover linear-gradient
CSSKeywordValue
display: none
, none
is a CSSKeywordValue
CSSStyleValue . parse ( ' display ' , ' none ' );
// CSSKeywordValue { value: 'none' }
const keywordValue = new CSSKeywordValue ( ' flex ' );
// CSSKeywordValue { value: 'flex' }
keywordValue . value ;
// 'flex'
Enter fullscreen mode
Exit fullscreen mode
CSSNumericValue
CSSNumericValue has a few subclasses, eg: CSSUnitValue, CSSMathValue
// Convert units
CSS . px ( 48 ). to ( ' in ' )
// CSSUnitValue { value: 0.5, unit: 'in' }
CSS . px ( 48 ). to ( ' rem ' )
// Error
// Cannot transform absolute unit to relative unit
Enter fullscreen mode
Exit fullscreen mode
CSSMathValue
CSSMathNegate, CSSMathMin, CSSMathMax, CSSMathSum, CSSMathProduct, CSSMathInvert
new CSSMathSum ( CSS . px ( 5 ), CSS . px ( 10 )); // 15px
div . attributeStyleMap . set ( ' width ' , new CSSMathMax ( CSS . rem ( 10 ), CSS . px ( 30 )));
// <div style="width: max(10rem, 30px)"></div>
Enter fullscreen mode
Exit fullscreen mode
CSSPositionValue
const position = new CSSPositionValue ( CSS . px ( 20 ), CSS . px ( 50 ))
position . x ; // CSSUnitValue { value: 20, unit: 'px' }
position . y ; // CSSUnitValue { value: 50, unit: 'px' }
Enter fullscreen mode
Exit fullscreen mode
CSSTransformValue
CSSTranslate, CSSScale, CSSRotate, CSSSkew, CSSSkewX, CSSSkewY, CSSPerspective, CSSMatrixComponent
const transformValue = CSSStyleValue . parse ( ' transform ' , ' translate3d(10px, 20px, 30px) scale(1.5) ' );
// iterate through each transformation
for ( const transform of transformValue ) {
console . log ( transform );
}
// CSSTranslate { ... }
// CSSScale { ... }
// get DOMMatrix out of the transformValue
transformValue . toMatrix ();
// DOMMatrix { a: 1.5, b: 0, c: 0, ... }
Enter fullscreen mode
Exit fullscreen mode
CSSUnparsedValue
CSSCustomProperty, that is not Houdini Property
the value is parsed as string
<script>
const element = document . querySelector ( ' #app ' );
element . attributeStyleMap . get ( ' --length ' );
// CSSUnparsedValue { 0: 3px }
</script>
<div id= "app" style= "--length: 3px;" >
Enter fullscreen mode
Exit fullscreen mode
References
Top comments (1)
About 3 years since this post, this CSS Typed OM and other Houdini features like defining/declaring custom properties is still like an experimental. I mean, Firefox still does not support them, making me hesitate on using them.