CSS if() Function: Conditional Styling Without JavaScript
The if() function brings real conditional logic to CSS. Write cleaner, more powerful styles with native branching
CSS if() Function: Conditional Logic is Finally Here
After years of workarounds, CSS finally has a native if() function. No more hacks, no more JavaScript for simple conditional styling.
The Syntax
property: if( condition: value; condition: value; else: fallback;);It works like a switch statement — first match wins.
Real Example: Responsive Grid
.grid { display: grid; grid-template-columns: if( media(width > 900px): repeat(auto-fit, minmax(200px, 1fr)); media(width > 600px): repeat(3, 1fr); media(width > 300px): repeat(2, 1fr); else: 1fr; );}One property. All breakpoints. No separate media queries needed.
Condition Types
The if() function supports three condition types:
1. Media Queries
.sidebar { width: if( media(width >= 1024px): 300px; else: 100%; );}2. Feature Queries
.container { display: if( supports(display: grid): grid; else: flex; );}3. Style Queries (Custom Properties)
.card { --theme: dark; background: if( style(--theme: dark): #1a1a2e; style(--theme: light): #ffffff; else: #f0f0f0; );}Dynamic Theming Example
.button { --variant: primary; background-color: if( style(--variant: primary): #7c3aed; style(--variant: secondary): #6b7280; style(--variant: danger): #dc2626; else: #3b82f6; ); color: if( style(--variant: secondary): #1f2937; else: white; );}<button style="--variant: primary">Save</button><button style="--variant: danger">Delete</button>No classes needed — just change the custom property!
Status Cards with Data Attributes
.status { border-color: if( style(--status: success): #22c55e; style(--status: warning): #f59e0b; style(--status: error): #ef4444; else: #6b7280; );}<div class="status" style="--status: success">Connected</div><div class="status" style="--status: error">Failed</div>Combining with @function
CSS now also has custom functions with @function:
@function --spacing(--size) { result: if( style(--size: sm): 0.5rem; style(--size: md): 1rem; style(--size: lg): 2rem; else: 1rem; );}
.card { padding: --spacing(--size: lg); margin: --spacing(--size: md);}Browser Support
Currently Chrome 137+ only. But it's coming to other browsers.
Progressive enhancement:
/* Fallback */.sidebar { width: 100%;}
/* Modern browsers */.sidebar { width: if( media(width >= 1024px): 300px; else: 100%; );}vs Traditional Approach
Before:
.grid { display: grid; grid-template-columns: 1fr;}
@media (min-width: 300px) { .grid { grid-template-columns: repeat(2, 1fr); }}
@media (min-width: 600px) { .grid { grid-template-columns: repeat(3, 1fr); }}
@media (min-width: 900px) { .grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }}After:
.grid { display: grid; grid-template-columns: if( media(width > 900px): repeat(auto-fit, minmax(200px, 1fr)); media(width > 600px): repeat(3, 1fr); media(width > 300px): repeat(2, 1fr); else: 1fr; );}Same result. Way less code. All in one place.
Live Demo: Traditional CSS Grid
While if() is Chrome-only for now, here's a live example of the traditional responsive grid approach that works everywhere:
Resize the preview to see the grid adapt!
Key Takeaways
if()returns a single value based on conditions- Use
media()for viewport/device queries - Use
supports()for feature detection - Use
style()for custom property checks - First matching condition wins
- Works great with CSS custom properties for dynamic theming
The future of CSS is looking very programmable. 🚀
Stay Updated 📬
Get the latest tips and tutorials delivered to your inbox. No spam, unsubscribe anytime.