CSS Functions
Native CSS functions and conditional logic for dynamic styling
Overview
Shift CSS includes a powerful set of native CSS functions using the @function rule and if() conditional logic. These enable dynamic, self-healing components without JavaScript or preprocessors.
Browser Support
| Browser | Version | Support |
|---|---|---|
| Chrome | 139+ | ✅ Full |
| Edge | 139+ | ✅ Full |
| Firefox | Experimental | 🔄 Behind flag |
| Safari | Experimental | 🔄 Behind flag |
Import
/* Full framework (includes all utilities) */
@import "@shift-css/core";
/* Or import just functions */
@import "@shift-css/core/utils/functions";
Color Functions
—s-alpha
Add transparency to any color.
.overlay {
background: --s-alpha(var(--s-primary-500), 0.5);
}
Parameters:
--color: The base color--opacity: Opacity value (0-1)
—s-lighten / —s-darken
Adjust the lightness of a color using OKLCH.
.hover-state {
background: --s-lighten(var(--s-primary-500), 0.1);
}
.pressed-state {
background: --s-darken(var(--s-primary-500), 0.1);
}
Parameters:
--color: The base color--amount: Amount to adjust (0-1, e.g., 0.1 = 10%)
—s-saturate / —s-desaturate
Adjust the chroma (saturation) of a color.
.vibrant {
color: --s-saturate(var(--s-primary-500), 0.1);
}
.muted {
color: --s-desaturate(var(--s-primary-500), 0.1);
}
—s-hue-rotate
Shift the hue of a color by degrees.
.shifted {
background: --s-hue-rotate(var(--s-primary-500), 30);
}
—s-complement
Get the complementary color (180° hue shift).
.accent {
border-color: --s-complement(var(--s-primary-500));
}
Effect Functions
—s-glow
Generate a multi-layered glowing box-shadow.
.glowing-card {
box-shadow: --s-glow(var(--s-primary-500), 2);
}
.intense-glow {
box-shadow: --s-glow(var(--s-accent-500), 4);
}
Parameters:
--color: The glow color--intensity: Intensity multiplier (1-5)
—s-text-shadow-glow
Generate a text glow effect.
.neon-text {
text-shadow: --s-text-shadow-glow(var(--s-accent-500), 2);
}
Contrast Functions
—s-contrast-text
Automatically return black or white text based on background lightness. Uses a 0.6 OKLCH lightness threshold as a pragmatic heuristic for contrast.
Note: WCAG contrast ratios use relative luminance (sRGB) with a different crossover point (~0.179). This function provides a practical OKLCH-based approximation, not a true WCAG luminance calculation.
.auto-text {
background: var(--dynamic-bg);
color: --s-contrast-text(var(--dynamic-bg));
}
—s-readable-on
Ensure text is readable on a given background by adjusting its lightness.
.readable {
color: --s-readable-on(var(--bg-color), var(--text-color));
}
Conditional Styling with if()
The if() function enables inline conditional logic based on media queries, style queries, or feature queries.
Responsive Values
Replace media queries with inline conditionals:
[s-responsive-padding] {
padding: if(
media(width < 640px): var(--s-space-2) ;
media(width < 1024px): var(--s-space-4) ; else: var(--s-space-6) ;
);
}
Motion Preferences
Respect user motion preferences inline:
[s-motion-safe] {
transition-duration: if(
media(prefers-reduced-motion: reduce): 0ms; else: var(--s-duration-200) ;
);
}
Dark Mode Awareness
Adapt to color scheme preferences:
[s-dark-aware] {
background-color: if(
media(prefers-color-scheme: dark): var(--s-surface-sunken) ;
else: var(--s-surface-raised) ;
);
}
Size Variants with Style Queries
Create size-aware components using custom property state:
[s-size-aware] {
--size: md; /* default */
padding: if(
style(--size: sm): var(--s-space-2) ; style(--size: lg): var(--s-space-6) ;
else: var(--s-space-4) ;
);
font-size: if(
style(--size: sm): var(--s-text-sm) ; style(--size: lg): var(--s-text-lg) ;
else: var(--s-text-base) ;
);
}
<div s-size-aware style="--size: lg">Large size variant</div>
<div s-size-aware style="--size: sm">Small size variant</div>
Built-in Utility Attributes
s-auto-contrast
Cards with automatic text contrast based on background:
<article s-card s-auto-contrast style="--_card-bg: var(--s-primary-500)">
Text automatically contrasts with the background
</article>
s-responsive-padding
Responsive padding without media queries:
<div s-responsive-padding>Padding adjusts based on viewport width</div>
s-motion-safe
Respects reduced motion preferences:
<div s-motion-safe>Transitions disabled for motion-sensitive users</div>
s-dark-aware
A sophisticated dark-awareness system that goes beyond simple color swaps. It provides:
- Container-Relative Theming - Uses CSS style queries to detect parent theme context, not just system preference
- OKLCH Perceptual Contrast - Auto-computes readable text color based on background lightness
- Visual Adaptations - Subtle border glow prevents bleeding, font weight adjusts for halation
Dark-Aware in Both Themes
Self-Healing Card
Text contrast, border glow, and font weight all adapt automatically.
Self-Healing Card
Text contrast, border glow, and font weight all adapt automatically.
<div s-dark-aware style="padding: 1rem;">
<h4 style="margin-bottom: 0.5rem;">Self-Healing Card</h4>
<p>Text contrast, border glow, and font weight all adapt automatically.</p>
</div> Theme Containers
Create “dark islands” on light pages (or vice versa) with s-theme:
<!-- Explicit dark container on a light page -->
<aside s-theme="dark">
<div s-dark-aware>Inherits dark context from parent</div>
</aside>
<!-- Follows system preference -->
<div s-dark-aware>Falls back to OS preference</div>
Theme Islands
Forced light context
Forced dark context
<div style="display: flex; gap: 1rem;">
<div s-theme="light" style="flex: 1; padding: 1rem; border: 1px solid oklch(0.8 0 0);">
<div s-dark-aware style="padding: 1rem;">
<strong>Light Island</strong>
<p style="margin-top: 0.25rem;">Forced light context</p>
</div>
</div>
<div s-theme="dark" style="flex: 1; padding: 1rem; border: 1px solid oklch(0.3 0 0);">
<div s-dark-aware style="padding: 1rem;">
<strong>Dark Island</strong>
<p style="margin-top: 0.25rem;">Forced dark context</p>
</div>
</div>
</div> Variants
<!-- Default: background, text, glow, weight adjustment -->
<div s-dark-aware>Full adaptation</div>
<!-- Subtle: text and weight only, no background -->
<div s-dark-aware="subtle">For inline elements</div>
<!-- Strong: more pronounced glow for hero sections -->
<div s-dark-aware="strong">Maximum visual separation</div>
Technical Details
| Feature | Light Mode | Dark Mode |
|---|---|---|
| Text Color | OKLCH L=0.15 | OKLCH L=0.95 |
| Border Glow | None | 0.5px white @ 8% |
| Font Weight | Base | Base - 50 |
The font weight reduction counters halation - the optical illusion where light text on dark backgrounds appears “fatter” due to light bleed in human vision.
Creating Custom Functions
Define your own reusable CSS functions:
@function --my-shadow(--color, --size) {
result: 0 calc(var(--size) * 2px) calc(var(--size) * 4px)
oklch(from var(--color) l c h / 0.3);
}
.custom-card {
box-shadow: --my-shadow(var(--s-primary-500), 4);
}
Fallback Strategies
For browsers without @function or if() support, provide fallbacks:
/* Fallback value first, enhanced value second */
.element {
color: var(--s-text-primary);
/* Browsers without @function support ignore invalid values */
color: --s-contrast-text(var(--bg));
}
Or use @supports to detect @function support:
@supports at-rule(@function) {
.element {
color: --s-contrast-text(var(--bg));
}
}
Note: The cascade approach (fallback first, function second) is generally preferred as it’s simpler and doesn’t require feature detection.