Frontend
-
CSS Finally Got Inline Conditionals
I’ve been digging into some of the newer features landing in CSS, and inline conditionals with the
if()function jumped out as one of the more interesting ones. The idea of writing a condition right next to the property it affects, instead of opening a separate@mediablock ten lines away, sounds useful. So this post is my attempt at summarizing what I found. I hope it helps if you’re trying to figure out whatif()actually does and where it fits.What It Actually Does
The shape is condition, colon, value, with an optional
elsebranch:property: if(<condition>: <value>; else: <fallback>;);You evaluate something, you get back a value, and the property uses that value. The
else:branch is optional. If you leave it off and the condition fails, the property falls back to its inherited or initial value.That’s it.
What makes it powerful is what you can put in that condition slot. Three kinds of queries are supported:
media()for viewport and device conditions,style()for custom property values on the element, andsupports()for feature detection. The same things you’ve always been able to ask CSS, but now you can ask them inline, right next to the property they affect.Theming Without the Yo-Yo
Dark mode is the most obvious win.
.card { background-color: white; color: black; } @media (prefers-color-scheme: dark) { .card { background-color: #333; color: white; } }And here’s the same thing with
if():.card { background-color: if(media(prefers-color-scheme: dark): #333; else: white;); color: if(media(prefers-color-scheme: dark): white; else: black;); }The logic lives next to the property. You don’t have to hunt down a separate block to figure out what happens in dark mode. When you change the light color, the dark color is right there staring at you. That’s a real maintenance win, especially in a stylesheet that’s been touched by five different people.
Variants Without Modifier Classes
This is the example that makes the case best. Component libraries are drowning in modifier classes.
.btn-primary,.btn-danger,.btn-success, on and on. Every one of them is just a different background color and maybe a border.With
if()and a custom property, you can collapse the whole thing:.button { padding: 10px 20px; border-radius: 6px; color: white; background-color: if( style(--variant: danger): red; style(--variant: success): green; else: blue; ); }<button class="button">Submit</button> <button class="button" style="--variant: danger;">Delete</button>No JavaScript reading props and toggling class names. No BEM modifier soup. You set a variable, the CSS reacts. The component owns its own logic.
Feature Detection Inline
The same pattern works for graceful degradation when you want a newer feature with a fallback:
.element { display: if(supports(display: grid): grid; else: flex;); color: if( supports(color: lch(75% 0 0)): lch(75% 0 0); else: rgb(185 185 185); ); }This used to require a dedicated
@supportsblock with the property repeated inside. Now it doesn’t.Observations
A few things are happening here that go deeper than syntactic sugar.
The first is bloat reduction. A component that used to need a base class plus four modifier classes plus a media query block can be one selector. Multiply that across a design system and the savings get real.
The second is encapsulation. A component’s stylesheet can carry its own logic without relying on a JavaScript framework to compute the right class name and shove it into the DOM. The CSS engine is doing the work, natively, and it’s a lot faster at this than your render loop is.
If the logic lives where the value lives, you don’t context-switch to figure out why a property has the value it does. You read the property, you read the condition, you understand it, you move on.
That’s the same reason inline error handling beats a separate try/catch block ten lines away. Co-location is a maintenance superpower.
Browser Support
Browser support is still narrow. Chrome shipped
if()in version 137, but Firefox and Safari haven’t followed yet, so this isn’t something to drop into a production stylesheet without a fallback. The pattern is to declare a plain value first and then override withif(), so non-supporting browsers ignore the line they don’t understand:.card { background-color: white; background-color: if(media(prefers-color-scheme: dark): #333; else: white;); }The syntax has also shifted through CSS Working Group drafts, so older articles you find about
if()may show a comma-ternary form that no longer works. Check MDN before copying anything.But the direction is right. CSS has been quietly absorbing more and more of the work we used to push to JavaScript, and
if()is one of the bigger steps in that direction. I’ll probably keep poking at it.Sources
- if() CSS function — MDN
- CSS conditionals with the new if() function — Chrome for Developers
- Lightly Poking at the CSS if() Function in Chrome 137 — CSS-Tricks
- CSS if() function — Can I use
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
/ Web development / Css / Frontend