preface

While we’ve been styling DOM elements for a long time, we’re actually manipulating the CSS object model CSSOM. Houdini promotes another set of CSS object model Typed OM. What benefits does this standard bring to us?

CSSOM

What does CSSOM do?

In simple terms, CSSOM is a set of apis that allow JS to manipulate element CSS. It plays a very important role in the process of page rendering by the browser. The rendering steps of the browser roughly include:

  1. Parsing the HTML content and building it into A DOM object
  2. Parses the CSS content and builds it into CSSOM objects
  3. The browser combines the DOM and CSSOM into a render tree
  4. Eventually the browser renders the result

Problems faced

In normal development, we use the style object on the element to get the style of the element:

const cover = document.getElementById('cover');
cover.style.opacity; // Suppose it is 0.5
Copy the code

Then we reduce the transparency a little bit based on this:

cover.style.opacity += 0.3;
Copy the code

So, what’s wrong with that? First let’s look at the types of values:

typeof cover.style.opacity; // string
Copy the code

What a suprise! , so in fact, the operation above to reduce transparency actually produces a value of 0.50.3, which is clearly a problematic operation. Similarly, 200px strings are returned for attributes such as height, and getComputedStyles returns the same value. If you want to fit these values into a series of mathematical calculations, you must first convert them to numeric objects. To solve these problems, Typed OM emerged.

Typed OM

The appearance of Typed OM adds a new way for us to read and set values. Different from CSSOM, the Typed OM shows CSSOM values as a map in the attributeStyleMap of elements. The values of the rules are more useable JavaScript objects.

Benefits brought about

  1. Fewer bugs, as shown earlier, and operations via TypedOM to reduce this type of problem;
  2. The simple arithmetic operation method can be called on the numerical object, and the unit conversion can be done easily between the absolute units.
  3. CSSOM performance has been further improved due to the reduction of string operations. Tests provided by Tab Akins show that Typed OM operations are about 30% faster than CSSOM strings.
  4. Error handling, which throws an error for the wrong CSS value;
  5. Keep the key names consistent with the normal CSS style, and do not test the edge of backgroundColor and background-color.
  6. Due to theattributeStyleMapAs well ascomputedStyleMapObject is amapThat means we can use standardsmapAll methods provided in.

Browser Support

Current implementation of major browser vendors:

Intent to Implement: Intent to implement

Shipped: has been published

No signal: indicates No intention

Google Chrome and Opera were implemented in version 66 and 53, respectively.

Availability detection methods

You can check whether it is available by:

window.CSS && CSS.number
Copy the code

use

Basic read and assign methods

In Typed OM, the number and the unit of the number are separated. It gets a CSSUnitValue object with two internal keys: value and unit.

To assign a style to an element, you can also accept strings in addition to using css.px constructs
el.attributeStyleMap.set('height', CSS.px(10));
el.attributeStyleMap.set('height'.'10px');

// For fetch, return the CSSUnitValue object, whose value property is accessed to obtain a numeric value
el.attributeStyleMap.get('height').value; / / 10
el.attributeStyleMap.get('height').unit; // 'px'
Copy the code

CSS Numeric types

Typed OM, we have two basic numeric types. One is the simple numeric plus unit numbers mentioned in the example above. They belong to the CSSUnitValue type. For expressions that are more than a single number plus units or are evaluated using CALC, they are of type CSSMathValue.

CSSUnitValue

As mentioned above, CSSUnitValue represents a simple CSS value of number plus unit, but you can also construct one by using new on it. In most cases, you can also construct it directly from the CSS object’s method of the same name:

const num = CSS.number('10');
// num.value -> 10 num.unit -> 'number'

const px = CSS.px(42);
// px.value -> 42 px.unit -> 'px'

// We can also construct one using the new method
const deg = new CSSUnitValue(45.'deg');
// deg.value -> 45 deg.unit -> 'deg'
Copy the code

For a complete list of methods, you can view the contents of CSS Typed OM drafts.

CSSMathValue

If you want to express values that involve more than one value and use calC to evaluate the expression, use CSSMathValue. It should be noted that after calc is evaluated by the browser in actual use, it gets the calculation result, namely a CSSUnitValue value.

Since expressions are involved, operators are necessary. CSSMathValue also provides basic mathematical operators:

Calc (100vw + -10px)
new CSSMathSum(CSS.vw(100), CSS.px(- 10));

Calc (45deg * 3.1415926)
new CSSMathProduct(CSS.deg(45), CSS.number(Math.PI));

Calc (-10px)
new CSSMathNegate(CSS.px(10));

// Take the reciprocal: calc(1/10px);
new CSSMathInvert(CSS.px(10));

// Scope limit: calc(1px);
// The first parameter is the minimum value, the third parameter is the maximum value, and the middle value is the value to be clamped
new CSSMathClamp(1.- 1.3);

// Max: Max (10%, 10px)
new CSSMathMax(CSS.percent(10), CSS.px(10));

// 最小值: min(10%, 10px)
new CSSMathMin(CSS.percent(10), CSS.px(10));
Copy the code

What if the expression needs to be more complicated?

For example, if you want to build an expression: calc(1px * (3px + 2em)), you can do the following nesting:

new CSSMathProduct(CSS.px(1), new CSSMathSum(CSS.px(3), CSS.em(2)));
Copy the code

Mathematical operation method

CSSMathValue and CSSUnitValue both inherit from CSSNumericValue, and naturally inherit from CSSNumericValue’s mathematical operations, which are convenient to use:

// Add 1px + 1px
CSS.px(1).add(1);

// Subtract: 1px - 1px
CSS.px(1).sub(1);

// Multiply: 1px by 3px
CSS.px(1).mul(3);

// Divide: 1px into 3px
CSS.px(1).div(3);

// Compare the maximum value: Max (50%, 50vw);
CSS.percent(50).max(CSS.vw(50));

// Minimum value: min(50vh, 50vw);
CSS.vh(50).min(CSS.vw(50));

// The equality comparison method returns a Boolean value true
CSS.px(200).equals(CSS.px(200));
Copy the code

The addition, subtraction, multiplication and division operations also support multiple parameters

// Add calc(10px + 10vw + 10%)
CSS.px(10).add(CSS.vw(10), CSS.percent(10));
Copy the code

In addition, absolute units can be interchangeable:

CSS.in(9).to('cm').value; 
/ / 22.860000000000003
Copy the code

CSS Transform Value type

For the Transform property of CSSTransform, the above basic value expression cannot be satisfied, so we need to use CSSTransformValue. To build CSSTransformValue, we can pass in the following parameters:

  1. CSSRotateRotation:
  2. CSSScale: zoom
  3. CSSSkewTilt:
  4. CSSSkewX: X axis tilt
  5. CSSSkewY: The Y-axis is tilted
  6. CSSTranslate: transform
  7. CSSPerspectivePerspective:

Note that skew(x, y) and skewX(x) skewY(y) have different results as usual

It’s just as easy to use:

Transform: rotateX(45deg) Scale (0.5) translate3D (10px, 10px, 10px);
new CSSTransformValue([
    new CSSRotate(CSS.deg(45)),
    new CSSScale(CSS.number(0.5), CSS.number(0.5)),
    new CSSTranslate(CSS.px(10), CSS.px(10), CSS.px(10)));Copy the code

For the CSSTranslate type, you can also access the is2D method on the object to see if the current translate is2D or 3D. At the same time, the toMatrix method can be called to obtain the DOMMatrix matrix object.

CSS position value type

For properties that need to describe x/y positions, such as object-position, the CSSPositionValue type is used.

const pos = new CSSPositionValue(CSS.px(5), CSS.px(10));
// pos.y.value -> 10 pos.x.value -> 10
Copy the code

Numerical analysis

Since we can get string rules on objects of Type OM using the toString() method, can we use the API to parse string rules into types of Type OM? The answer is yes. Use the parse method in CSSStyleValue:

CSSStyleValue.parse('transform'.'translate (10 px) scale (0.5)');
// Will parse into a CSSTransformValue object

CSSStyleValue.parse('height'.'2px');
// The CSSUnitValue type will be resolved
Copy the code

computedStyleMap

The computedStyleMap method on the element returns all of the calculated attribute values, just like the traditional call to the window.getComputedStyle method. But there are still some small differences. Window.getcomputedstyle still returns string values; For the computedStyleMap method, the value returned is converted to the Type OM value Type.

document.body.attributeStyleMap.set('opacity'.1); 

document.body.computedStyleMap().get('opacity').value;
/ / 1

window.getComputedStyle(document.body).opacity;
/ / '1'
Copy the code

Typed OM role in Other Houdini standards

Since Typed OM refers to the numbers of CSSOM, then the numbers in the standards related to it will all be related to it. The Typed values Typed by the CSS Paint API are also numeric types Typed in CSS Typed OM.

In addition, the use of Typed OM is laying the foundation for the more efficient development of various Houdini standards (including custom attributes, layout and drawing standards).

conclusion

CSS Typed OM solves the problem of modifying values at development time. It also increases the overall performance by reducing the number of string operations, making CSSOM easy and efficient to manipulate. RequestAnimationFrame can also produce custom animations with better performance.

Refer to the link

Drafts.css-houdini.org/css-typed-o…

Developers.google.com/web/updates…

Rocks1635.rssing.com/chan-409413…

Thank you

Thanks to Teacher An Jia for her suggestions on this paper