Customized properties – aka “CSS variables” – appear pretty simple. Nevertheless, there are some behaviors to pay attention to concerning how the browser computes the ultimate values. A misunderstanding of this course of might result in an sudden or lacking worth and issue troubleshooting and resolving the difficulty.
That will help you use customized properties confidently and troubleshoot effectively, we’ll overview:
- how the browser determines values for any property
- the influence of “computed worth time”
- pitfalls round utilizing customized properties with cutting-edge CSS
- why inheritance ought to inform your customized property structure
Computed, Inherited, and Preliminary Values
When the browser parses CSS, its objective is to calculate one worth per property per factor within the DOM.
One thing you study early on about CSS is that you could change a property’s worth a number of occasions from a number of guidelines that will choose the identical factor.
Given the HTML <h2 class="card__title">
, the entire following are eligible matches for the colour
property.
physique {
colour: #222;
}
h2 {
colour: #74e;
}
.card__title {
colour: #93b;
}
Every of those are declared values, and on account of specificity and the cascading order, the factor’s ultimate chosen worth would be the cascaded worth. On this case, .card__title
wins for the colour
property.
If a property doesn’t obtain a price from the cascade, then it’ll use both the inherited or preliminary worth.
- Inherited values come from the closest ancestor that has assigned a price, if the property is allowed to inherit (ex.
colour
, font properties,text-align
) - Preliminary values are used when no inherited worth exists or is allowed and are the values offered by the specification for the property
So, for <h2 class="card__title">
, the complete set of values populated for the factor could also be as follows:
.card__title {
colour: #93b;
show: block;
line-height: 1.2;
font-family: Supply Code Professional;
font-weight: 500;
font-size: 1.35rem;
}
Some property definitions require additional computation to absolutize the values. The next are a couple of of the worth transforms that will happen.
- Relative items corresponding to
vw
,em
, and%
are transformed to pixel values, and floats could also be transformed to integers currentColor
and named colours likerebeccapurple
are transformed to ansRGB
worth- Compositing values that have an effect on one another
- ex.
padding: 1em
requires computing the worth forfont-size
thatem
depends upon
- ex.
- customized properties are changed with their computed values
These transformations end result within the computed, used, and precise values – which consult with the progressive steps which may be concerned to finish up with an absolutized worth. You may dive deeper into the specifics of how values are calculated or take a look at this overview of worth processing.
Customized Properties and Computed Worth Time
One particular computation situation with a essential influence on fashionable CSS is when the browser assigns values to customized properties, known as “computed worth time” (CVT).
Invalid at Computed Worth Time
As described earlier, usually unfilled, or invalid property assignments will fall again to cascaded values when relevant.
p { colour: blue }
.card p { colour: #notacolor; }
Take a second to see in the event you can decide what the colour
worth of .card p
will probably be within the following instance.
html { colour: purple; }
p { colour: blue; }
.card { --color: #notacolor; }
.card p { colour: var(--color); }
The .card p
would be the inherited colour
worth of purple
as offered by the physique
. It’s unable to make use of the cascaded worth of blue
as a result of browser discarding that as a attainable worth candidate at “parse time” when it is just evaluating syntax. It’s only when the person agent makes an attempt to use the ultimate worth – the stage of “computed worth time” – that it realizes the worth is invalid.
Stated one other method: as soon as the browser determines the cascaded worth, which is partially based mostly on syntactic correctness, it’ll trash some other candidates. For syntactically right customized properties, the browser basically assumes the absolutized worth will achieve being legitimate.
This results in an lack of ability for customized properties to “fail early”. When there’s a failure, the ensuing worth will probably be both an inherited worth from an ancestor or the preliminary worth for the property. (If this sounds acquainted, it’s as a result of it’s additionally the conduct when utilizing unset
.)
Critically, this implies an invalid customized property worth is unable to fall again to a beforehand set cascaded worth, as it’s possible you’ll count on, as a result of these have been discarded from the choice tree.
All hope shouldn’t be misplaced! If later a utility class on the paragraph have been to replace the colour
property, then on account of guidelines of the cascade and specificity it will win out like regular and the invalid customized property worth wouldn’t have an impact.
html { colour: purple; }
p { colour: blue; }
.card { --color: #notacolor; }
.card p { colour: var(--color); }
.card .callout { colour: purple }
Word that when referring to invalid values for customized properties that what makes it invalid is how the worth is utilized. For instance, an area character is a sound customized property definition, however will probably be invalid when utilized to a property.
:root {
--toggle: ;
}
.card {
margin: var(--toggle);
}
However, a customized property with a price of 100%
could also be utilized to width
however not colour
.
:root {
--length: 100%;
}
.card {
width: var(--length);
colour: var(--length);
}
CVT Influence on Fashionable CSS Assist
One other situation the place a customized property being invalid at computed worth time might break your expectation is utilizing the customized property as a partial worth, or undefined with a fallback, particularly paired with cutting-edge CSS options.
Given the next, it’s possible you’ll count on that when the cqi
unit shouldn’t be supported, the browser will merely use the prior font-size
definition.
h2 {
font-size: clamp(1.25rem, var(--h2-fluid, 1rem + 1.5vw), 2.5rem);
font-size: clamp(1.25rem, var(--h2-fluid, 5cqi), 2.5rem);
}
As a substitute, the browser assumes it’ll perceive the second clamp()
definition and discards the prior font-size
definitions for this h2
rule. However when the browser goes to populate the customized property worth and finds it doesn’t help cqi
, it’s too late to make use of what was supposed because the fallback definition. This implies it as an alternative makes use of the preliminary worth, if there isn’t a inheritable worth from an ancestor.
When you may suppose that the preliminary worth would at the very least be a font-size
befitting the h2
degree, the preliminary worth for any factor’s font-size
is “medium” which is mostly equal to 1rem
. This implies you not solely lose your supposed fallback fashion, but additionally the visible hierarchy of the h2
in browsers which don’t help cqi
.
One option to uncover the preliminary
worth for any property is to seek for it on MDN, and search for the “Formal Definition” part which can listing the preliminary worth, in addition to whether or not the worth is eligible for inheritance.
A couple of preliminary
values to pay attention to moreover font-size
:
background-color
:clear
border-color
:currentColor
border-width
:medium
which equates to3px
colour
:canvastext
which is a system colour and more likely to be black, however might change on account of forced-colors modesfont-family
: depends upon person agent, more likely to be a serif
Safely Supporting Fashionable CSS Values in Customized Properties
A safer answer is to wrap the definition utilizing cqi
in an @helps
in order that un-supporting browsers truly use the fallback.
h2 {
font-size: clamp(1.25rem, var(--h2-fluid, 1rem + 1.5vw), 2.5rem);
}
@helps (font-size: 1cqi) {
h2 {
font-size: clamp(1.25rem, var(--h2-fluid, 5cqi), 2.5rem);
}
}
Does this imply you must change each place you utilize customized properties? That every one depends upon your help matrix (which browsers and variations you could have elected to help). For super-ultra-modern properties, particularly when the preliminary worth is undesirable, this strategy would be the most secure. One other instance of when it’s possible you’ll use an @helps
situation is with new colour areas, like oklch()
.
Study extra about CSS characteristic detection that can assist you select the precise route on your undertaking.
Confusingly, given a state of affairs just like the cqi
instance, browser dev instruments for the un-supporting browser should present the failing rule as being the utilized fashion. That is probably as a result of the browser should help the opposite elements, like clamp()
. An incorrect look in dev instruments could make it troublesome to troubleshoot points brought on by customized properties being invalid at computed time, which is why it’s necessary to basically perceive what is going on.
Inheritance and Customized Properties
One other method computed worth time impacts customized property worth task is inheritance of computed values.
Calculation of a customized property worth is carried out as soon as per factor, which then makes the computed worth out there for inheritance. Let’s learn the way that impacts your customized property structure selections.
Inheritable Values Turn into Immutable
A typical conference is batching customized properties into the :root
selector. If a kind of properties includes a calculation which incorporates one other :root
-level customized property, then updating the modifying property from a descendent won’t replace the calculation.
As within the following instance, the --font-size-large
is calculated instantly, so updating the --font-size
property inside a descendent rule will be unable to have an effect on the worth.
CSS for “Computed values are immutable”
:root {
--font-size: 1rem;
--font-size-large: calc(2 * var(--font-size));
}
h1 {
--font-size: 1.25rem;
font-size: var(--font-size-large);
}
Cake muffin toffee gingerbread ice cream
It is because the calculation occurs as quickly because the browser processes the definition towards the :root
. So the :root
definition produces a static, computed worth which is inheritable, however immutable.
This isn’t to say this conduct is exclusive to :root
. The important thing idea is that when customized property values are computed, the computed worth is simply inheritable.
To consider it one other method: throughout the cascade, values could be inherited by descendents, however can’t cross values again to their ancestors. Basically that is why the computed customized property worth on an ancestor factor can’t be modified by a descendent factor.
Enabling Extendable Customized Property Values
If we decrease the customized property calculation to be utilized based mostly on lessons, then the browser will have the ability to recalculate as a part of the worth processing to find out the computed worth. It is because it’ll calculate a price for parts with the category font-resize
, and a separate worth for parts with each font-resize
and font-large
lessons.
CSS for “Computed values are per factor”
:root {
--font-size: 1rem;
}
.font-resize {
font-size: calc(var(--font-size-adjust, 1) * var(--font-size));
}
.font-large {
--font-size-adjust: 2.5;
}
Cake muffin toffee gingerbread ice cream
Stopping Invalid at Computed Worth Time
A couple of easy methods to keep away from customized property failure embody:
- Use a fallback worth when defining a customized property, which is the second worth that may be offered to the
var()
perform, ex.var(--my-property, 1px)
- Guarantee fallback values inside
var()
are of the proper sort for the property - In the event you’re utilizing a polyfill for a brand new characteristic, verify that it resolves utilization in customized properties as you count on
- Use
@helps
to make sure your supposed fashionable CSS improve doesn’t break supposed fallback guidelines in un-supporting browsers
And as all the time – check your options in as many browsers and on as many units as you possibly can!