A couple of sirens went off a few weeks in the past when the CSS Working Group (CSSWG) resolved so as to add an if() conditional to the CSS Values Module Stage 5 specification. It was Lea Verou’s X submit that very same day that caught my consideration:
A historic day for CSS 😀🎉
When you write any elements used and/or styled by others, you know the way large that is!
background: if(model(–variant: success), var(–inexperienced));
Even in the event you don’t, this can enable issues like:
padding: if(var(–2xl), 1em, var(–xl) or var(–m),… pic.twitter.com/cXeqwBuXvK
— Lea Verou (@LeaVerou) June 13, 2024
Lea is the one who opened the GitHub concern resulting in the dialogue and in a stroke of coincidence — or serendipity, maybe — the decision got here in on her birthday. That needed to be fairly a whirlwind of a day! What did you get to your birthday? “Oh, you realize, simply an accepted proposal to the CSS spec.” Wild, simply wild.
The accepted proposal is a inexperienced mild for the CSSWG to work on the thought with the intent of circulating a draft specification for additional enter and concerns en path to, hopefully, turn out to be a really helpful CSS function. So, it’s gonna be a sizzling minute earlier than any of that is baked, that’s, if it will get absolutely baked.
However the concept of making use of kinds primarily based on a conditional requirement is tremendous thrilling and value an early have a look at the thought. I scribbled some notes about it on my weblog the identical day Lea posted to X and thought I’d distill these right here for posterity whereas rounding up extra particulars which have come up since then.
This isn’t a brand new concept
Many proposals are born from beforehand rejected proposals and if() isn’t any completely different. And, certainly, we’ve gained a number of CSS options in latest days that enable for conditional styling — :has() and Container Fashion Queries being two of the extra apparent examples. Lea even cites a 2018 ticket that appears and reads loads just like the accepted proposal.
The distinction?
Fashion queries had already shipped, and we may merely reference the identical syntax for situations (plus media() and helps() from Tab’s @when proposal) whereas within the 2018 proposal how situations would work was largely undefined.
Lea Verou, “Inline conditionals in CSS?”
I like how Lea factors out that CSS goes on to explain how CSS has at all times been a conditional language:
Of us… CSS had conditionals from the very starting. Each selector is basically a conditional!
Lea Verou, “Inline conditionals in CSS?”
True! The Cascade is the automobile for evaluating selectors and matching them to HTML components on a web page. What if() brings to the desk is a strategy to write inline situations with selectors.
Syntax
It boils right down to this:
<if()> = if( <container-query>, [<declaration-value>]{1, 2} )
…the place:
Values will be nested to provide a number of branches.
If a 3rd argument shouldn’t be supplied, it turns into equal to an empty token stream.
All of that is conceptual for the time being and nothing is ready in stone. We’re prone to see issues change because the CSSWG works on the function. However because it at the moment stands, the thought appears to revolve round specifying a situation, and setting one among two declared kinds — one because the “default” model, and one because the “up to date” model when a match happens.
.ingredient {
background-color:
/* If the model declares the next customized property: */
if(model(–variant: success),
var(–color-green-50), /* Matched situation */
var(–color-blue-50); /* Default model */
);
}
On this case, we’re on the lookout for a mode() situation the place a CSS variable known as –variant is asserted and is ready to a worth of success, and:
…if –variant is ready to success, we set the worth of success to –color-green-50 which is a variable mapped to some greenish shade worth.
…if –variant shouldn’t be set to success, we set the worth of the success to –color-blue-50 which is a variable mapped to some bluish shade worth.
The default model can be optionally available, so I feel it may be omitted in some instances for barely higher legibility:
.ingredient {
background-color:
/* If the model declares the next customized property: */
if(model(–variant: success),
var(–color-green-50) /* Matched situation */
);
}
The syntax definition up prime mentions that we may help a 3rd argument along with the matched situation and default model that permits us to nest situations inside situations:
background-color: if(
model(–variant: success), var(–color-success-60),
if(model(–variant: warning), var(–color-warning-60),
if(model(–variant: hazard), var(–color-danger-60),
if(model(–variant: main), var(–color-primary)
)
),
)
);
Oomph, appears like some wild inception is going on in there! Lea goes on to recommend a syntax that may lead to a a lot flatter construction:
<if()> = if(
[ <container-query>, [<declaration-value>]{2} ]#{0, },
<container-query>, [<declaration-value>]{1, 2}
)
In different phrases, nested situations are way more flat as they are often declared outdoors of the preliminary situation. Identical idea as earlier than, however a distinct syntax:
background-color: if(
model(–variant: success), var(–color-success-60),
model(–variant: warning), var(–color-warning-60),
model(–variant: hazard), var(–color-danger-60),
model(–variant: main), var(–color-primary)
);
So, somewhat than one if() assertion inside one other if() assertion, we will lump all the attainable matching situations right into a single assertion.
That is all associated to model queries
We’re trying to match an if() situation by querying a component’s kinds. There is no such thing as a corresponding dimension() operate for querying dimensions — container queries implicitly assume dimension:
.ingredient {
background: var(–color-primary);
/* Situation */
@container guardian (width >= 60ch) {
/* Utilized kinds */
background: var(–color-success-60);
}
}
And container queries turn out to be model queries once we name the model() operate as an alternative:
.ingredient {
background: orangered;
/* Situation */
@container guardian model(–variant: success) {
/* Utilized kinds */
background: dodgerblue;
}
}
Fashion queries make much more sense to me once they’re seen within the context of if(). With out if(), it’s simple to query the overall usefulness of favor queries. However on this mild, it’s clear that model queries are a part of a a lot larger image that goes past container queries alone.
There’s nonetheless loads of issues to suss out with the if() syntax. For instance, Tab Atkins describes a attainable situation that would result in confusion between what’s the matched situation and default model parameters. So, who is aware of how this all shakes out ultimately!
Circumstances supporting different situations
As we’ve already famous, if() is much from the one sort of conditional verify already supplied in CSS. What would it not appear like to jot down an inline conditional assertion that checks for different situations, akin to @helps and @media?
In code:
background-color: if(
helps( /* and so on. */ ),
@media( /* and so on. */ )
);
The problem can be container supporting dimension queries. As talked about earlier, there is no such thing as a specific dimension() operate; as an alternative it’s extra like an nameless operate.
@andruud has a succinctly describes the problem within the GitHub dialogue:
I don’t see why we couldn’t do helps() and media(), however dimension queries would trigger cycles with format which can be laborious/not possible to even detect. (That’s why we wanted the restrictions we at the moment have for dimension CQs within the first place.
“Can’t we already do that with [X] strategy?”
After we have been wanting on the syntax earlier, you could have observed that if() is simply as a lot about customized properties as it’s about conditionals. A number of workarounds have emerged over time to imitate what we’d acquire if() we may set a customized property worth conditionally, together with:
Utilizing customized properties as a Boolean to use kinds or not relying on whether or not it is the same as 0 or 1. (Ana has a beautiful article on this.)
Utilizing a placeholder customized property with an empty worth that’s set when one other customized property is ready, i.e. “the customized property toggle trick” as Chris describes it.
Container Fashion Queries! The issue (moreover lack of implementation) is that containers solely apply kinds to their descendants, i.e., they can’t apply kinds to themselves once they meet a sure situation, solely its contents.
Lea will get deep into this in a separate submit titled “Inline conditional statements in CSS, now?” that features a desk that outlines and compares approaches, which I’ll merely paste beneath. The reasons are stuffed with advanced CSS nerdery however are extraordinarily useful for understanding the necessity for if() and the way it compares to the intelligent “hacks” we’ve used for years.
MethodInput valuesOutput valuesProsConsBinary Linear InterpolationNumbersQuantitativeCan be used as a part of a valueLimited output varyTogglesvar(–alias) (precise values are too bizarre to show uncooked)AnyCan be utilized in a part of a valueWeird values that should be aliasedPaused animationsNumbersAnyNormal, decoupled declarationsTakes over animation property
Cascade weirdnessKind GrindingKeywordsAny worth supported by the syntax descriptorHigh flexibility for uncovered APIGood encapsulationMust insert CSS into mild DOM
Tedious code (although will be automated with construct instruments)
No Firefox help (although that’s altering)Variable animation titleKeywordsAnyNormal, decoupled declarationsImpractical outdoors of Shadow DOM as a result of title clashes
Takes over animation property
Cascade weirdness
Comfortable birthday, Lea!
Belated by two weeks, however thanks for sharing the spoils of your large day with us! 🎂
References
What’s the MVP for inline conditionals on customized properties? (Lea Verou, GitHub Situation #10064)
Inline conditionals in CSS? (Lea Verou)
Inline conditionals in CSS, now? (Lea Verou)
To Shared Hyperlink — Permalink on CSS-Tips
“If” CSS Will get Inline Conditionals initially revealed on CSS-Tips, which is a part of the DigitalOcean household. It’s best to get the e-newsletter.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!