CSS now has an if() conditional function

6 days ago (caniuse.com)

Give it enough time, every declarative language becomes a programming language. This is happening with all config files, markup languages, data formats.

The distinction between code, config and data is being erased. Everything is a soup now. Data is application, configuration is code. Code is an intermediate, volatile thing that is generated on the fly and executed in the temporary lambda containers.

  • > every declarative language becomes a programming language.

    Overly pessimistic, lots of non-programming languages remain non-programming languages. Just because one of the most widely used declarative languages start adding conditionals doesn't mean the whole world is turning upside down...

    > The distinction between code, config and data is being erased.

    As as lisp programmer, I love it. Get rid of treating things differently, make everything the same and make everything work with everything, code should just be data.

    • > Get rid of treating things differently, make everything the same and make everything work with everything, code should just be data.

      "Code should just be data" doesn't imply the converse, though; there's arguably utility in having data that isn't code, even with the premise that code should be data.

    • > Just because one of the most widely used declarative languages start adding conditionals doesn't mean the whole world is turning upside down.

      The question still is: why is CSS becoming a programming language? And who decides on this, anyway?

      10 replies →

    • If only Lisp had better presense in modern code editors. Emacs is not enough, especially on Windows where it is super slow. I think this is what actually stops newcomers to start with Lisp and not Python

      5 replies →

    • >> Just because one of the most widely used declarative languages start adding conditionals doesn't mean the whole world is turning upside down.

      You need to look at a large terraform project.

      1 reply →

  • An if conditional doesn't make a programming language. You need recursion to have Turing completeness.

    CSS already has all sorts of conditionals that are if() in disguise!

    For instance a selector like .foo means "if the class is foo then select this style block'.

    CSS is thoroughly condition-driven already.

  • This is so true, I have seen it happen with so many projects. It always starts with a cute declarative DSL, and inevitably imperative / flow control structures emerge, at which point you wonder why they didn't use a real programming language in the first place and save you the hassle or learning a half baked imperative DSL.

    - Puppet

    - CMake

    - Terraform

    - ...

    All these started with pure declarative DSL then incrementally created a nightmarish imperative monstrosity.

    • CMake was never declarative AFAIK?

      CMake today is effectively an eso-lang / Turing tarpit with some “modern” declarative conventions that people try to push.

      1 reply →

    • People love to hate on Maven's XML but at least it's been mostly the same since 2006. There are conditionals in profile activation expressions but they are very limited by design. Declarative done right, IMO

    • > All these started with pure declarative DSL then incrementally created a nightmarish imperative monstrosity.

      "Huh?" I asked myself when you mentioned that Terraform is now imperative somehow. Took a look at the website again, and seems to still be HCL, and still be declarative. Am I missing something? How exactly is Terraform today a "imperative monstrosity"?

      5 replies →

  • Conditional expressions are declarative. For example, every template language worth its salt has conditionals.

    A programming (i.e Turing complete) language requires recursion or a construct of equal power.

  • An interesting example is the Dhall language: https://dhall-lang.org/

    It is a configuration language with general programming features, but it is decidedly _not_ Turing complete. It seems to sit at a sweet spot between "just JSON, no programming convenience at all" and "full-blown programming language with nontrivial toolchain".

  • > The distinction between code, config and data is being erased.

    This distinction never existed in LISP. Greenspun's tenth rule in action.

  • We can blame von Neumann (et al) and his infernal architecture, where memory stores both instructions and data.

    • You can blame whoever invented the word "if", as soon as you can branch based on data you can just write an interpreter that turns data into instructions, no matter the architecture.

      7 replies →

    • FWIW, you can make software that runs on Harvard architecture chips. They feature distinct address spaces for ROM and RAM. It's been a while, but it's how Atmel/Microchip AVR micros work.

      https://en.wikipedia.org/wiki/Harvard_architecture

      That said, I'm unaware of any programming language (outside assembler) that takes that split to heart in a higher-level way.

    • Not really, most of these configuration as code systems are not executed directly on the CPU but rather interpreted in which case a separate data-only memory would not stop anyone.

    • von Neumann did not invent the von Neumann architecture. Not even a little bit.

      If you want to reason that the hardware is at fault, you should be blaming the Eckert-Mauchley architecture.

      1 reply →

  • Unfortunely too many people are afraid of opening parentheses being posited on the far left instead of the middle of the text.

    • It was shocking the first time I showed a lisp program to a (particularly "annoyed by everything") non-lisp developer who never apparently saw s-expressions before. Lots of knee-jerk reactions of "Oh my god so many parenthesis" and "How could anyone program like this?" while they sat there smug with their TypeScript codebase having more special characters, syntax and the same amount of parenthesizes, only because the opening parenthesis is one symbol to the left, instead of in the middle of the calls...

  • can someone interpret this as not a skill issue?

    i want better, declarative, interactive, fast UIs

    CSS is the best answer we have

  • So why do people still design declarative languages?

    • OP is not being very precise (and in a way that I don't think is helpful). There is nothing imperative in an if expression. Declarative languages can be Turing complete. Declarative languages are a subset of programming languages.

    • If you can mostly stick to the declarative way, it's still a benefit. No Turing-complete language completely prevents you from writing "bad" code. "You are not completely prevented from doing things that are hard to understand" is a bad argument. "You are encouraged to do things that are hard to understand" is a good one (looking at you, Perl).

    • Wishful thinking? Maybe they are tired of all this and want to make something good again, and so the cycle continues.

    • It’s the cycle of newcomers to <field> looking at the existing solutions and declaring “this shit is too complicated, why did these morons design it this way? Check out my DSL that does everything and is super simple!”

      Then time passes, edge cases start cropping up and hacks are bolted on to accommodate them. Eventually everything struggles under the weight of not having loops, conditionals, etc. and those are added.

      After some time, the cycle begins anew.

  • I've been observing this, off and on, for decades now. Is there an actual formal proof or law named after someone at this point?

I'm pretty happy to see this, as conditionals can really help keep code manageable when trying to define CSS variables or other properties based on combinations of light mode, dark mode, high-contrast, contextual state in a document or component, etc.

if() isn't the only way to do this, though. We've been using a technique in Review Board that's roughly equivalent to if(), but compatible with any browser supporting CSS variables. It involves:

1. Defining your conditions based on selectors/media queries (say, a dark mode media selector, light mode, some data attribute on a component, etc.).

2. Defining a set of related CSS variables within those to mark which are TRUE (using an empty value) and which are FALSE (`initial`).

3. Using those CSS variables with fallback syntax to choose a value based on which is TRUE (using `var(--my-state, fallback)` syntax).

I wrote about it all here, with a handful of working examples: https://chipx86.blog/2025/08/08/what-if-using-conditional-cs...

Also includes a comparison between if() and this approach, so you can more easily get a sense of how they both work.

  • I recently implemented dark/light mode for the first time and was really surprised to find that in order to add a toggle I had to duplicate a both of vars/styles and use JavaScript. I'm looking forward to not having to deal with that cruft in the future.

Far from being ready when only one major browser supports it. If you want this, you should vote for it to be focused on for interop-2026

https://github.com/web-platform-tests/interop/issues

Right now, the leading CSS proposals are `@container style()`, `corner-shape` and `break-after`

https://foolip.github.io/interop-reactions/

  • Yeesh.. I've definitely tried using break-after and being disappointed it didn't work properly. The amount of hoops I had to jump through to get things to print properly on paper...

    • Agreed. This has come up multiple times during my job. It's gotten to the point where we had a microservice running that spun up selenium and printed the dom and then sent that pdf back to the front-end all just to make consistent print outputs. I've read tech blogs of others doing just that too so it's not uncommon.

      Unfortunately the test set of wpt does not have the capability to cover printed matter so relief isn't coming any time soon

just a meta note that the submitter, aanthonymax, likely only posted this to launder karma to avoid being shadowed for spamming their github project. a quick look at their post history shows that they only post links to their github project and then occasionally extremely low effort random mdn or other useless links to try to balance our their account. their previous account was shadowed for basically the same thing

It's a great way to make conditional styles without having to use JavaScript; however, having used JS for years to make theme color and icon sets that rely on CSS properties, I'm not sure I particularly like this method. I feel like you have to smear a lot of logic across your CSS whereas with JS you can reduce your theme to a data structure and just have a simple function to setup all the CSS variables based on that.

Am I just an old man?

  • The primary goal is to just have a more concise way to do @media queries. Its not intended as a replacement for most uses of JS

    • If we've learned anything from the history of CSS, JS and the semantic web it is that 99% of the time a feature will be used in ways that were not intended. There is no reason to suppose that this will be any different.

      1 reply →

  • I like making static informational pages and don't know the first thing about JavaScript, so this could be handy for me.

  • Javascript always suffer from FOUC problem though (Unless it's server side). Although the if() css function seems to just be syntax suger of standard @media query. So it doesn't really add anything to solve existing problems.

    Edited: It seems it can also be toggled from css variable? So it might actually fix some existing problems.

    • How hard would it be to have a response header that tells the browser "don't display anything at all until we ask you to from JS when we're ready"?

      Considering the kinds of crap that have been done with headers...

      4 replies →

  • You're pulling the old man card on CSS-in-JS? Putting your style logic in CSS is what CSS is for, CSS-in-JS is an annoying hack to make React work. What this is replacing is SCSS.

    • Well, historically, styles were first in JS (JS StyleSheets in Netscape 4.0) and were pulled out into CSS. – This is an old man card! ;-)

Here is a much better link to how it works: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/V...

  •   padding: 1em;
      padding: if(style(--size: "2xl"): 1em; else: 0.25em);
    

    > Note: Remember to include the else condition. In if()-supporting browsers, if no else value were included and --size was not equal to "2xl", the padding would be set to initial.

    This is counterintuitive. You would expect the above falls back to "1em" (from "padding: 1em;") when "else" is not specified. Instead, omitting "else" apparently means "else: initial".

I'm kind of thankful not having to work with people trying to be clever in CSS anymore (especially "clever" backend developers).

And I used to defend and evangelize taking HTML&CSS seriously in my previous roles, which I'd still do!

But as much as I have longed for features like these in the past (also: :has(), container queries, custom properties...), I dislike this.

I found CSS grid disappointing for most use cases.

I think :has() is a terrible idea, except for quick hacks.

I still think container queries and custom properties are good.

But, oh well, old man yelling at cloud.

I'm not sure turning CSS into a full blown language is a good idea. With all the cascading in place, it is already a bit hard to determine why certain styles are applied. Now with this, we will be spending more brain cells debugging CSS issues.

  • On the contrary, a lot of the reason CSS is confusing is because it's full of insane hacks people have to do to get the behaviour they want. A straight-up if statement is much simpler than many of the horrors I've seen.

  • css definitely shouldn't have backwards branches (loops/recursive functions), but adding a little more power can clean up expression a ton and make reading/applying that much faster

    • I wish the "little more power" would add CSS modules. It would also be great if web components didn't require Javascript and could be configured with pure HTML and CSS.

      I will kiss the feet of the whatwg groups if they do this.

      PS: Would also love to have declarative template inclusion now that removal of XSLT has also removed this facility from the browser.

As long as css remains "so fast it's free" then I'm mostly happy with that - I use css without thinking about optimisations, and I like it like that!

  • You can certainly write slow CSS, and people do :-) JavaScript typically takes up more of the CPU time overall, though.

  • Well, you can actually write slow css if you make real deep nested flex container. And it's not even too rare. You can actually find such example in yhe wild.

    The spec of flex layout requires it to layout its child elements several times to compute actual layout. Make it deep and nested without proper constrains will results in n*n*n*n… layout computations and bring down the browser on resize.

    • It’s not even that hard. Use flex for layout and you can instantly see how slow reflow becomes when resizing the window.

  • It's not free at all. You can profile it with debug tools and find the most expensive selectors to refactor them. You can also write CSS animations that impacts performance/user experience, this can also be profiled.

    Sorry but if you use advanced feature and especially on a big DOM, you have to think about optimisations.

With the inclusion of branches, is it possible to say that CSS is now even more Turing-Complete? Now we just need to find ways to do recursion/targeted jumps so that it is finally recursive-enumerable

  • Don’t apply programming language mental models onto CSS features.

    CSS if() probably just merges one of two single-property RuleSets onto the parent RuleSet depending on the condition, which has nothing to do with branching, as there is no execution flow to branch.

If we could do it over, knowing that we'd eventually get to this point, would https://en.wikipedia.org/wiki/JavaScript_Style_Sheets have been the better path?

Huh. 35 year ago I was the sole maintainer of an in-house SQL-like database query language. The application was transforming relational data into a more concise and efficient format for use in an embedded application (AT&T 5ESS digital switch). All the mapping was done in this SQL-like language. One of my power users mentioned the difficulty they had in actually changing logic based on the values in the database. For example, to perform different logic based on whether a column was a 1 or a 2, they'd have to write two querys: one for 1 and another for 2. Possible, sure, but not very clean or efficient. To address this, I implemented an if() function.

So we were looking in the wrong direction for AGI!

  • Replying to myself (hey, I like myself and I'd like to have a conversation with me):

    CSS doesn't have it right? Just Chrome.

    Considering how all kinds of "experts" have started to make web sites that only work fine in Chrome [1], this is not exactly a useful new feature, more like embrace and extend...

    [1] Orange Romania, when will I be able to download my invoices again in Firefox?

One of the nice things working in vite is realising, “hey, this config file is just {Java,Type}Script”.

Can it already vertically and horizontally center unknown-beforehand-length multi-line text in a single html element, just like non-CSS table cells could already in 1995?

  • > Can it already vertically and horizontally center unknown-beforehand-length multi-line text in a single html element, just like non-CSS table cells could already in 1995?

    Non-CSS table cells have never been able to do that – you need a wrapping <table> at minimum for browsers to render it how you want, a <tr> for it to be valid HTML, and <tbody> comes along for the ride as well as an implied element. So that’s four elements if you want to centre vertically with <td> or <th>. If you wait until the year 2000, then you can get that down to three elements by switching from HTML to XHTML because <tbody> is no longer implied in XHTML.

    CSS, on the other hand, has been able to do what you want since 1998 (CSS 2) with only two elements:

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
        <title>.</title>
        <style type="text/css">
    
            html,
            body {
                height: 100%;
            }
    
            .outer {
                display: table;
                width: 100%;
                height: 100%;
            }
    
            .inner {
                display: table-cell;
                vertical-align: middle;
                text-align: center;
            }
    
        </style>
        <div class="outer">
            <div class="inner">
                Test<br>
                Test<br>
                Test<br>
                Test<br>
                Test<br>
                Test
            </div>
        </div>
    

    (I’m using a <style> element here for clarity, but you can do the same thing with style attributes.)

    https://www.w3.org/TR/1998/REC-CSS2-19980512/

  • align-content: center;

    (supported on block elements since sometime last year)

    • Thanks, seems to work at first sight in combination with text-align for the horizontal alignment!

      That means I may finally not need line-height or multi-element tricks for this anymore

      Interesting that this is finally there since a year!

      I wonder what made them decide to support it finally, since CSS's creation in 1996.

      A button never looks professional if the text in it isn't centered, this was a really needed feature and I still can't understand why it took that long

      Edit: it does seem worrying that for me this property vertically centers but not horizontally while the description of it doesn't say vertical but is: "The items are packed flush to each other in the center of the alignment container along the cross axis."

I'm not really sure I understand this. How is the new if() conditional function different from using @media (width ...) when adapting layouts to browser width?

  • Its basically the same, just more convinent syntax.

    I think if can also do string equality on variable values, which is a bit new but also niche. The main point is just to do @media but inside a property decleration.

If I'm reading this correctly, Opera added support in an earlier version then took it away again. Any idea why they might have done it? Maybe a browser engine change under the hood?

I guess we can now write Excel in CSS.

  • Interesting, a few organizations can (very) carefully craft their own LOB software over the number of years it can take to fully free themselves from Excel. And then realize the intended advantage for years to come.

    At the same time over a period of years the web approach is to make the whole thing more like a bunch of interlocked Excels, more so than it already was before.

    Does that mean any resulting disadvantage during following years is intentional? Any more than huge orgs grew to depend on Excel, one physical desktop at a time since that was the only thing in common among all those diverse desk owners that would do the job, plus it was the first thing to come along to fill that niche.

Not supported in Firefox and Safari. Also it seems most people forget that the more bloated the web platform is, the more resources are needed to develop and maintain a web browser engine.. Chromium is open-source, but it's already expensive to maintain a fork or even rebuild it..

  • They just need to start deprecating and removing old features. They had no issues with XSLT removal even when some major sites like the library of congress used it. So the excuse of backward compatability has already proven to be a lie.

  • [flagged]

    • > How did this happen?

      That's pretty simple - Google has poured tons of money into Chrome and Mozilla. Google is not a charity so this was a strategic investment.

      > You should go over to the CSS working group and let them know

      That wouldn't work, money is what ultimately matters there.

      7 replies →

Nice, does it make turing complete? If so, another crap to block under Dillo.

That's what happens when you design a language by comitee (C++, JS) and try to do stuff in the web for a platform made to share static documents.

Just look at what kind of disasters the users faced with Office macros.

This is missing a "if variable equals" imho. Right now it seems like pure syntactic sugar for a media query.

Nice. I've built desktop apps in a few other frameworks e.g. Java Swing, JavaFX, JetBrains Compose, SwiftUI, QT. Nothing is as easy as JS/HTML/CSS. I've realized that the main reason is its robust capabilities e.g rich auto-layouting/positioning capabilities.

Meanwhile in other UI frameworks, you either don't do it or you draw the damn things yourself lol. So, most of the times I'd just not do it.

Adding if is great. It would reduce the need for JS a bit more, which would make the code more maintainable.