Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Coded Smorgasbord: High Strung

      September 26, 2025

      Chainguard launches trusted collection of verified JavaScript libraries

      September 26, 2025

      CData launches Connect AI to provide agents access to enterprise data sources

      September 26, 2025

      PostgreSQL 18 adds asynchronous I/O to improve performance

      September 26, 2025

      Distribution Release: Neptune 9.0

      September 25, 2025

      Distribution Release: Kali Linux 2025.3

      September 23, 2025

      Distribution Release: SysLinuxOS 13

      September 23, 2025

      Development Release: MX Linux 25 Beta 1

      September 22, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      PHP 8.5.0 RC 1 available for testing

      September 26, 2025
      Recent

      PHP 8.5.0 RC 1 available for testing

      September 26, 2025

      Terraform Code Generator Using Ollama and CodeGemma

      September 26, 2025

      Beyond Denial: How AI Concierge Services Can Transform Healthcare from Reactive to Proactive

      September 25, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Distribution Release: Neptune 9.0

      September 25, 2025
      Recent

      Distribution Release: Neptune 9.0

      September 25, 2025

      FOSS Weekly #25.39: Kill Switch Phones, LMDE 7, Zorin OS 18 Beta, Polybar, Apt History and More Linux Stuff

      September 25, 2025

      Distribution Release: Kali Linux 2025.3

      September 23, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»News & Updates»Poking at the CSS if() Function a Little More: Conditional Color Theming

    Poking at the CSS if() Function a Little More: Conditional Color Theming

    June 25, 2025

    Chrome 137 shipped the if() CSS function, so it’s totally possible we’ll see other browsers implement it, though it’s tough to know exactly when. Whatever the case, if() enables us to use values conditionally, which we can already do with queries and other functions (e.g., media queries and the light-dark() function), so I’m sure you’re wondering: What exactly does if() do?

    Sunkanmi gave us a nice overview of the function yesterday, poking at the syntax at a high level. I’d like to poke at it a little harder in this article, getting into some possible real-world usage.

    To recap, if() conditionally assigns a value to a property based on the value of a CSS variable. For example, we could assign different values to the color and background properties based on the value of --theme:

    • --theme: "Shamrock"
      • color: ‌hsl(146 50% 3%)
      • background: hsl(146 50% 40%)
    • --theme: Anything else
      • color: hsl(43 74% 3%)
      • background: hsl(43 74% 64%)
    :root {
      /* Change to fall back to the ‘else’ values */
      --theme: "Shamrock";
    
      body {
        color: if(style(--theme: "Shamrock"): hsl(146 50% 3%); else: hsl(43 74% 3%));
        background: if(style(--theme: "Shamrock"): hsl(146 50% 40%); else: hsl(43 74% 64%));
      }
    }
    CodePen Embed Fallback

    I don’t love the syntax (too many colons, brackets, and so on), but we can format it like this (which I think is a bit clearer):

    color: if(
      style(--theme: "Shamrock"): hsl(146 50% 3%);
      else: hsl(43 74% 3%)
    );

    We should be able to do a crazy number of things with if(), and I hope that becomes the case eventually, but I did some testing and learned that the syntax above is the only one that works. We can’t base the condition on the value of an ordinary CSS property (instead of a custom property), HTML attribute (using attr()), or any other value. For now, at least, the condition must be based on the value of a custom property (CSS variable).

    Exploring what we can do with if()

    Judging from that first example, it’s clear that we can use if() for theming (and design systems overall). While we could utilize the light-dark() function for this, what if the themes aren’t strictly light and dark, or what if we want to have more than two themes or light and dark modes for each theme? Well, that’s what if() can be used for.

    First, let’s create more themes/more conditions:

    :root {
      /* Shamrock | Saffron | Amethyst */
      --theme: "Saffron"; /* ...I choose you! */
    
      body {
        color: if(
          style(--theme: "Shamrock"): hsl(146 50% 3%);
          style(--theme: "Saffron"): hsl(43 74% 3%);
          style(--theme: "Amethyst"): hsl(282 47% 3%)
        );
        background: if(
          style(--theme: "Shamrock"): hsl(146 50% 40%);
          style(--theme: "Saffron"): hsl(43 74% 64%);
          style(--theme: "Amethyst"): hsl(282 47% 56%)
        );
        transition: 300ms;
      }
    }

    Pretty simple really, but there are a few easy-to-miss things. Firstly, there’s no “else condition” this time, which means that if the theme isn’t Shamrock, Saffron, or Amethyst, the default browser styles are used. Otherwise, the if() function resolves to the value of the first true statement, which is the Saffron theme in this case. Secondly, transitions work right out of the box; in the demo below, I’ve added a user interface for toggling the --theme, and for the transition, literally just transition: 300ms alongside the if() functions:

    CodePen Embed Fallback

    Note: if theme-swapping is user-controlled, such as selecting an option, you don’t actually need if() at all. You can just use the logic that I’ve used at the beginning of the demo (:root:has(#shamrock:checked) { /* Styles */ }). Amit Sheen has an excellent demonstration over at Smashing Magazine.

    To make the code more maintainable though, we can slide the colors into CSS variables as well, then use them in the if() functions, then slide the if() functions themselves into CSS variables:

    /* Setup */
    :root {
      /* Shamrock | Saffron | Amethyst */
      --theme: "Shamrock"; /* ...I choose you! */
    
      /* Base colors */
      --shamrock: hsl(146 50% 40%);
      --saffron: hsl(43 74% 64%);
      --amethyst: hsl(282 47% 56%);
    
      /* Base colors, but at 3% lightness */
      --shamrock-complementary: hsl(from var(--shamrock) h s 3%);
      --saffron-complementary: hsl(from var(--saffron) h s 3%);
      --amethyst-complementary: hsl(from var(--amethyst) h s 3%);
    
      --background: if(
        style(--theme: "Shamrock"): var(--shamrock);
        style(--theme: "Saffron"): var(--saffron);
        style(--theme: "Amethyst"): var(--amethyst)
      );
    
      --color: if(
        style(--theme: "Shamrock"): var(--shamrock-complementary);
        style(--theme: "Saffron"): var(--saffron-complementary);
        style(--theme: "Amethyst"): var(--amethyst-complementary)
      );
    
      /* Usage */
      body {
        /* One variable, all ifs! */
        background: var(--background);
        color: var(--color);
        accent-color: var(--color);
    
        /* Can’t forget this! */
        transition: 300ms;
      }
    }
    CodePen Embed Fallback

    As well as using CSS variables within the if() function, we can also nest other functions. In the example below, I’ve thrown light-dark() in there, which basically inverts the colors for dark mode:

    --background: if(
      style(--theme: "Shamrock"): light-dark(var(--shamrock), var(--shamrock-complementary));
      style(--theme: "Saffron"): light-dark(var(--saffron), var(--saffron-complementary));
      style(--theme: "Amethyst"): light-dark(var(--amethyst), var(--amethyst-complementary))
    );
    CodePen Embed Fallback

    if() vs. Container style queries

    If you haven’t used container style queries before, they basically check if a container has a certain CSS variable (much like the if() function). Here’s the exact same example/demo but with container style queries instead of the if() function:

    :root {
      /* Shamrock | Saffron | Amethyst */
      --theme: "Shamrock"; /* ...I choose you! */
    
      --shamrock: hsl(146 50% 40%);
      --saffron: hsl(43 74% 64%);
      --amethyst: hsl(282 47% 56%);
    
      --shamrock-complementary: hsl(from var(--shamrock) h s 3%);
      --saffron-complementary: hsl(from var(--saffron) h s 3%);
      --amethyst-complementary: hsl(from var(--amethyst) h s 3%);
    
      body {
        /* Container has chosen Shamrock! */
        @container style(--theme: "Shamrock") {
          --background: light-dark(var(--shamrock), var(--shamrock-complementary));
          --color: light-dark(var(--shamrock-complementary), var(--shamrock));
        }
    
        @container style(--theme: "Saffron") {
          --background: light-dark(var(--saffron), var(--saffron-complementary));
          --color: light-dark(var(--saffron-complementary), var(--saffron));
        }
    
        @container style(--theme: "Amethyst") {
          --background: light-dark(var(--amethyst), var(--amethyst-complementary));
          --color: light-dark(var(--amethyst-complementary), var(--amethyst));
        }
    
        background: var(--background);
        color: var(--color);
        accent-color: var(--color);
        transition: 300ms;
      }
    }
    CodePen Embed Fallback

    As you can see, where if() facilitates conditional values, container style queries facilitate conditional properties and values. Other than that, it really is just a different syntax.

    Additional things you can do with if() (but might not realize)

    Check if a CSS variable exists:

    /* Hide icons if variable isn’t set */
    .icon {
      display: if(
        style(--icon-family): inline-block;
        else: none
      );
    }

    Create more-complex conditional statements:

    h1 {
      font-size: if(
        style(--largerHeadings: true): xxx-large;
        style(--theme: "themeWithLargerHeadings"): xxx-large
      );
    }

    Check if two CSS variables match:

    /* If #s2 has the same background as #s1, add a border */
    #s2 {
      border-top: if(
        style(--s2-background: var(--s1-background)): thin solid red
      );
    }

    if() and calc(): When the math isn’t mathing

    This won’t work (maybe someone can help me pinpoint why):

    div {
      /* 3/3 = 1 */
      --calc: calc(3/3);
      /* Blue, because if() won’t calculate --calc */
      background: if(style(--calc: 1): red; else: blue);
    }

    To make if() calculate --calc, we’ll need to register the CSS variable using <a href="https://css-tricks.com/almanac/rules/p/property/">@property</a> first, like this:

    @property --calc {
      syntax: "<number>";
      initial-value: 0;
      inherits: false;
    }

    Closing thoughts

    Although I’m not keen on the syntax and how unreadable it can sometimes look (especially if it’s formatted on one line), I’m mega excited to see how if() evolves. I’d love to be able to use it with ordinary properties (e.g., color: if(style(background: white): black; style(background: black): white);) to avoid having to set CSS variables where possible.

    It’d also be awesome if calc() calculations could be calculated on the fly without having to register the variable.

    That being said, I’m still super happy with what if() does currently, and can’t wait to build even simpler design systems.


    Poking at the CSS if() Function a Little More: Conditional Color Theming originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleIntehill 16″ 3K Touchscreen U16ZT Portable Monitor Review
    Next Article CVE-2025-48954 – Discourse is an open-source discussion platform. V

    Related Posts

    News & Updates

    Distribution Release: Neptune 9.0

    September 25, 2025
    News & Updates

    Distribution Release: Kali Linux 2025.3

    September 23, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    CVE-2025-48875 – FreeScout Cross-Site Scripting (XSS) Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Microsoft’s June 2025 Patch Tuesday: 2 Zero-Days, 69 Vulnerabilities Patched!

    Security

    CVE-2025-5559 – WordPress TimeZoneCalculator Stored Cross-Site Scripting Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    You Are What You Eat: Why Your AI Security Tools Are Only as Strong as the Data You Feed Them

    Development

    Highlights

    Why Smart Parents in Nagpur Are Choosing Early Vaccination for Their Babies

    May 10, 2025

    Post Content Source: Read More 

    Chrome Android Will Soon Catch Your Grammar Mistakes

    August 4, 2025

    Microsoft wants app developers to infuse Windows 11 with AI features

    May 17, 2025

    UC Berkeley Introduces CyberGym: A Real-World Cybersecurity Evaluation Framework to Evaluate AI Agents on Large-Scale Vulnerabilities Across Massive Codebases

    June 20, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.