Let's see how we create a CSSMathValue
and whilst doing so see what is available within the type:
const mathVal = new CSSMathSum(CSS.px(10), CSS.vw(20));
/*
Returns: CSSMathSum {
operator: "sum",
values: CSSNumericArray
0: CSSUnitValue {value: 10, unit: "px"},
1: CSSUnitValue {value: 20, unit: "vw"},
length: 2
}
*/
This creates a new CSSMathValue
with the operator type "sum". CSSMathValue
s always take CSSUnitValue
s. As you can see with what is created in the above example, CSSMathSum
actually takes a CSSNumericArray
which is an array of CSSNumericValue
s.
If we use the toString()
method on a CSSMathValue
, it returns the ready made calc()
function as a string. Handy.
console.log(mathVal.toString());
// Logs: calc(10px + 20vw)
NB As with the previous part on numeric types, there is an associated javascript file which you can find here. It is logging code to the console which you can see in the developer tools pane.
Other CSSMathValue
types that associate with the calc()
function are 'sum', 'product', 'negate' and 'invert'. Each of the mathematical operations returns it's own interface. Here's an example of each them, how to create each, set()
the value on an element and in turn get()
that value to see the interface returned:
CSSMathSum
Addition & Subtraction. Values are of type CSSNumericValue
and it takes a CSSNumericArray
, so you can put in as many values as you want.
const sumVal = new CSSMathSum(CSS.px(10), CSS.vw(20), CSS.em(1.2));
el.attributeStyleMap.set('width', sumVal);
const gotSumVal = el.attributeStyleMap.get('width');
/*
Returns: CSSMathSum {
operator: "sum",
values: CSSNumericArray
0: CSSUnitValue {value: 10, unit: "px"},
1: CSSUnitValue {value: 20, unit: "vw"},
2: CSSUnitValue {value: 1.2, unit: "em"},
length: 3
}
*/
To subtract use a negative number
const subVal = new CSSMathSum(CSS.s(2), CSS.ms(-200));
el.attributeStyleMap.set('animation-duration', subVal);
const gotSubVal = el.attributeStyleMap.get('animation-duration');
/*
Returns: CSSMathSum {
operator: "sum",
values: CSSNumericArray
0: CSSUnitValue {value: 2, unit: "s"},
1: CSSUnitValue {value: -200, unit: "ms"},
length: 2
}
*/
CSSMathProduct
Multiplication. Again here you can pass in a CSSNumericArray
.
const productVal = new CSSMathProduct(CSS.em(1.6), CSS.number(1.2));
el.attributeStyleMap.set('font-size', productVal);
const gotProductVal = el.attributeStyleMap.get('font-size');
/*
Returns: CSSMathProduct {
operator: "product",
values: CSSNumericArray
0: CSSUnitValue {value: 1.6, unit: "em"},
1: CSSUnitValue {value: 1.2, unit: "number"},
length: 2
}
*/
CSSMathNegate
Negation. Only takes one CSSNumericValue
. Note here how we have to use the aforementioned toString()
method, as the type itself does not negate the value, it just specifies it is of negated type.
const negVal = new CSSMathNegate(CSS.px(20));
// negVal.toString() returns 'calc(-20px)'
el.attributeStyleMap.set('margin-top', negVal.toString());
const gotNegVal = el.attributeStyleMap.get('margin-top');
/*
Returns: CSSMathNegate {
operator: "negate",
value: CSSUnitValue {value: 20, unit: "px"}
}
*/
The calc()
function is not the only mathematical function we have in CSS however, there is also the min()
, max()
and yet to be implemented clamp()
functions. These all have their own CSSMathValue
types. Let's take a look at creating each in turn, and what each interface contains.
CSSMathMin
Takes a CSSNumericArray
. If you are unfamiliar with the min() function you can find out more here.
const minVal = new CSSMathMin(CSS.vh(10), CSS.px(300));
/*
Returns: CSSMathMin {
operator: "min",
values: CSSNumericArray
0: CSSUnitValue {value: 10, unit: "vh"},
1: CSSUnitValue {value: 300, unit: "px"},
length: 2
}
*/
CSSMathMax
Again, takes a CSSNumericArray
. If you are unfamiliar with the max() function you can find out more here.
const maxVal = new CSSMathMax(CSS.px(50), CSS.percent(20));
/*
Returns: CSSMathMax {
operator: "max",
values: CSSNumericArray
0: CSSUnitValue {value: 50, unit: "px"},
1: CSSUnitValue {value: 20, unit: "percent"},
length: 2
}
*/
Nested calculations
In CSS you can nest any of the above functions: calc()
, min()
or max()
. Consider the following CSS: min( calc(1.2em * 1.4), 10vw)
, to recreate this using CSSMathValue
s we would also need to nest them:
const nestedVal = new CSSMathMin(
new CSSMathProduct(CSS.em(1.2), CSS.number(1.4)),
CSS.vw(10)
);
/*
Returns: CSSMathMin {
operator: "min",
values: CSSNumericArray
0: CSSMathProduct {
operator: "product"
values: CSSNumericArray
0: CSSUnitValue {value: 1.2, unit: "em"},
1: CSSUnitValue {value: 1.4, unit: "number"},
length: 2
}
1: CSSUnitValue {value: 300, unit: "px"},
length: 2
}
*/
On the surface this could seem overly complex, however it makes sense and we have to remember it's the underlying information about these CSSValueTypes
that is being exposed and we have access to. It might be a bit to take in at this point, but as support starts to advance and we gain familiarity with this API, we'll probably wonder how we ever managed without it.
There is also more. There's methods that each CSSNumericValue
is privy to, let's check them out in the next part.