CSS Just Got Conditional — No JavaScript Required 🚀

CSS Just Got Conditional — No JavaScript Required 🚀

firaflash


Imagine being able to set CSS properties directly based on conditions — without JavaScript, without preprocessors, without workarounds. With the new if() function in CSS, this is now a reality. The CSS if() function officially shipped in Chrome 137.

For years, we’ve relied on workarounds: JavaScript toggle classes, CSS preprocessor mixins, or endless media query blocks. The if() function puts an end to all that, bringing conditional logic directly into CSS — elegant, performant, and declarative.

How it works:

property: if(
  condition-1: value-1;
  condition-2: value-2;
  condition-3: value-3;
  else: default-value
);

The function checks conditions sequentially and applies the first matching value. If no condition matches, the else value is used — exactly as you’d expect from programming languages, but now in pure CSS.

The three capabilities of the if() function

1. Style queries

With style(), you can react to CSS Custom Properties:


.card {
  --status: attr(data-status type(<custom-ident>));
  
  border-color: if(
    style(--status: pending): royalblue;
    style(--status: complete): seagreen;
    style(--status: error): crimson;
    else: gray
  );
}

A single data-status attribute in HTML now controls the entire styling — no more utility classes needed!

2. Media queries

Forget nested media query blocks. With media(), you define responsive values inline:


h1 {
  font-size: if(
    media(width >= 1200px): 3rem;
    media(width >= 768px): 2.5rem;
    media(width >= 480px): 2rem;
    else: 1.75rem
  );

3. Feature detection

Gone are the days of random fallback strategies and hoping things work 😬. With supports(), you check browser features directly in the property:


.element {
  border-color: if(
    supports(color: lch(0 0 0)): lch(50% 100 150);
    supports(color: lab(0 0 0)): lab(50 100 -50);
    else: rgb(200, 100, 50)
  );
}

Real-world use cases

Dark mode in three lines

body {
  --theme: "dark"; /* Toggle via JavaScript or User Preference */
  
  background: if(
    style(--theme: "dark"): #1a1a1a;
    else: white
  );
  
  color: if(
    style(--theme: "dark"): #e4e4e4;
    else: #333
  );
}

Get Karsten Biedermann’s stories in your inbox

Join Medium for free to get updates from this writer.


Subscribe


Design system status components


.alert {
  --type: attr(data-type type(<custom-ident>));
  
  background: if(
    style(--type: success): #d4edda;
    style(--type: warning): #fff3cd;
    style(--type: danger): #f8d7da;
    style(--type: info): #d1ecf1;
    else: #f8f9fa
  );
  
  border-left: 4px solid if(
    style(--type: success): #28a745;
    style(--type: warning): #ffc107;
    style(--type: danger): #dc3545;
    style(--type: info): #17a2b8;
    else: #6c757d
  );
}

Container without media query chaos

.container {
  width: if(
    media(width >= 1400px): 1320px;
    media(width >= 1200px): 1140px;
    media(width >= 992px): 960px;
    media(width >= 768px): 720px;
    media(width >= 576px): 540px;
    else: 100%
  );
  
  padding-inline: if(
    media(width >= 768px): 2rem;
    else: 1rem
  );
}

Combining with modern CSS features 🤔

.element {
  /* With the new light-dark() function */
  color: if(
    style(--high-contrast: true): black;
    else: light-dark(#333, #e4e4e4)
  );
  
  /* With CSS Custom Functions (@function) */
  padding: if(
    style(--spacing: loose): --spacing-function(2);
    style(--spacing: tight): --spacing-function(0.5);
    else: --spacing-function(1)
  );
}

Browser support

As of August 2025:


  • ✅ Chrome/Edge: From version 137
  • ✅ Chrome Android: From version 139
  • ❌ Firefox: In development
  • ❌ Safari: On the roadmap
  • ❌ Opera: Not yet supported

Since support is still growing, you can use this pattern:

.button {
  /* Fallback for all browsers */
  padding: 1rem 2rem;
  background: #007bff;
  
  /* Modern browsers automatically override */
  padding: if(
    style(--size: small): 0.5rem 1rem;
    style(--size: large): 1.5rem 3rem;
    else: 1rem 2rem
  );
  
  background: if(
    style(--variant: primary): #007bff;
    style(--variant: success): #28a745;
    style(--variant: danger): #dc3545;
    else: #6c757d
  );
}

What the future holds

The CSS Working Group is already working on extensions:


  • Range Queries: if(style(--value > 100): ...)
  • Logical Operators: if(style(--a: true) and style(--b: false): ...)
  • Container Query Integration: Even more context-awareness

Report Page