I'm trying to scale the size via avar
custom property so that the classes can be composed without coupling. The desired effect is that the 3 lists will have 3 different scales, but as shown on CodePen, all 3 lists have the same scale. I'm looking for an explanation of scoping and CSS custom property techniques that can achieve this with composable, loosely coupled code.
:root { --size-1: calc(1 * var(--scale, 1) * 1rem); --size-2: calc(2 * var(--scale, 1) * 1rem); --size-3: calc(3 * var(--scale, 1) * 1rem); } .size-1 { font-size: var(--size-1) } .size-2 { font-size: var(--size-2) } .size-3 { font-size: var(--size-3) } .scale-1x { --scale: 1 } .scale-2x { --scale: 2 } .scale-3x { --scale: 3 } html { font: 1em sans-serif; background: papayawhip; } ol { float: left; list-style: none; margin: 1rem; }
- size 1
- size 2
- size 3
- size 1
- size 2
- size 3
- size 1
- size 2
- size 3
In your case you have evaluated the
--scale
custom properties at the root level to define the--size-*
properties and then defined the- -scale
Againwithin child elements. This will not trigger the evaluation again as it has already been done in theupper layer.The following is a simple example to illustrate this problem:
To solve your problem, you need to move the declaration from
:root
to the same level as the--scale
definition:In this case,
--scale
is defined at the same level as its evaluation, so--size-*
will be defined correctly for each case.FromSpecification:
In the first case you're stuck at3because no value is specified for
--scale
at the root level. In the last case we are stuck with2because we defined--scale
at the same level and we have its value.In all cases we should avoid any evaluation at the
:root
level as it is simply not useful. The root level is the top level in the DOM, so all elements will inherit the same value, it is impossible to have different values within the DOM unless we evaluate the variable again.Your code is equivalent to this code:
Let’s give another example:
Intuitively, we might think that we can change
--color
by changing one of the 3 variables defined at the:root
level, but we cannot do this with the above operation code Same as this:3 variables (
--r
,--g
,--b
) are evaluated within:root
code> therefore We have replaced them with their values.In this case we have 3 possibilities:
:root
. This doesn't allow us to have different colors::root
will become useless (or at least will become the default)::root
selector to the universal selector*
. This will ensure that our functions are defined and evaluated at all levels. In some complex cases this may produce some unwanted resultsWith this in mind, we should always keep evaluation to the lowest possible point in the DOM tree, especiallyafter a variable has changed(or at the same level)
This is something we shouldn’t do
this is what we are supposed to do
We can also do this: