CSS Functions: The Complete Guide for 2026

CSS functions are the computational backbone of modern stylesheets. They let you perform math, respond to screen sizes, reference custom properties, mix colors, and build complex layouts — all without a single line of JavaScript. In 2026, the CSS function landscape is richer than ever, with the full suite of math functions now shipping in every major browser.

This guide covers every CSS function you need to know, from the foundational calc() to the newest trigonometric and exponential functions. Each section includes practical, real-world examples you can use immediately.

calc() — Math Operations and Unit Mixing

The calc() function performs arithmetic directly in CSS. Its defining feature is the ability to mix different units in a single expression — something no other CSS mechanism can do.

Basic Operations

/* Addition and subtraction — must have spaces around + and - */
.sidebar {
    width: calc(100% - 300px);
    height: calc(100vh - 4rem);
}

/* Multiplication and division */
.column {
    width: calc(100% / 3);
    padding: calc(1rem * 1.5);
}

/* Mixing units freely */
.container {
    max-width: calc(80ch + 4rem);    /* character units + rem */
    margin-top: calc(2em + 10px);     /* em + px */
    width: calc(50vw - 2rem + 1px);   /* viewport + rem + px */
}

Real-World Patterns

/* Full-bleed element inside a constrained parent */
.full-bleed {
    width: calc(100vw - var(--scrollbar-width, 0px));
    margin-left: calc(-50vw + 50%);
}

/* Aspect ratio box (legacy approach — use aspect-ratio today) */
.ratio-box {
    height: 0;
    padding-bottom: calc(9 / 16 * 100%);
}

/* Responsive font scaling between breakpoints */
h1 {
    font-size: calc(1.5rem + 2vw);
}

/* Sticky footer: main content fills remaining viewport */
.main-content {
    min-height: calc(100vh - var(--header-height) - var(--footer-height));
}

/* Grid gap compensation */
.grid-item {
    width: calc((100% - 2 * 1rem) / 3);  /* 3 columns with 1rem gaps */
}

The spaces around + and - are required. Writing calc(100%-2rem) is invalid and will be silently ignored by the browser. Multiplication and division do not require spaces but including them improves readability.

⚙ Try it: Build gradient values that use calc() with our CSS Gradient Generator, then fine-tune the output in your stylesheets.

min(), max(), and clamp() — Responsive Sizing

These comparison functions replaced many media-query-based responsive patterns with single-line declarations. They accept comma-separated values and can mix units just like calc().

min() — The Smaller Value Wins

/* Container that never exceeds 1200px but shrinks on small screens */
.container {
    width: min(1200px, 100% - 2rem);
}

/* Image that scales down but never beyond its natural size */
img {
    width: min(100%, 600px);
}

/* Responsive padding */
section {
    padding: min(5vw, 3rem);
}

max() — The Larger Value Wins

/* Ensure minimum font size regardless of viewport */
.body-text {
    font-size: max(16px, 1vw);
}

/* Touch target that is at least 44px (accessibility) */
.button {
    min-height: max(44px, 2.75rem);
    min-width: max(44px, 2.75rem);
}

/* Sidebar that never collapses below 200px */
.sidebar {
    width: max(200px, 20vw);
}

clamp() — Value with Floor and Ceiling

clamp(minimum, preferred, maximum) is equivalent to max(minimum, min(preferred, maximum)). It is the single most useful function for responsive typography and spacing.

/* Responsive heading: grows with viewport but stays between 1.5rem and 3rem */
h1 {
    font-size: clamp(1.5rem, 4vw + 0.5rem, 3rem);
}

/* Fluid body text */
body {
    font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
}

/* Responsive container width */
.content {
    width: clamp(320px, 90%, 1200px);
    margin-inline: auto;
}

/* Fluid spacing scale */
:root {
    --space-sm: clamp(0.5rem, 1vw, 1rem);
    --space-md: clamp(1rem, 2vw, 2rem);
    --space-lg: clamp(2rem, 4vw, 4rem);
}

/* Line length for readability */
.prose {
    max-width: clamp(45ch, 70%, 75ch);
}

A practical formula for fluid typography: clamp(min, preferred, max) where the preferred value is typically vw-based with a rem offset. The formula clamp(1rem, 0.5rem + 1.5vw, 2rem) scales smoothly from 1rem on small screens to 2rem on large screens.

var() — Custom Properties

The var() function reads CSS custom properties. It accepts an optional fallback value as a second argument, and fallbacks can themselves contain var() references.

/* Basic usage */
:root {
    --color-primary: #3b82f6;
    --radius: 8px;
    --font-body: system-ui, -apple-system, sans-serif;
}

.card {
    background: var(--color-primary);
    border-radius: var(--radius);
    font-family: var(--font-body);
}

/* Fallback values */
.alert {
    color: var(--alert-color, #ef4444);           /* simple fallback */
    border: 1px solid var(--alert-border, var(--alert-color, #ef4444));  /* nested fallback */
}

/* Combining var() with calc() */
.grid {
    gap: calc(var(--base-spacing) * 2);
    padding: calc(var(--base-spacing) * 3);
}

/* Using var() inside other functions */
.hero {
    background: linear-gradient(var(--gradient-angle, 135deg), var(--color-start), var(--color-end));
    font-size: clamp(var(--min-size), var(--fluid-size), var(--max-size));
}

For an in-depth exploration of CSS custom properties including theming, dark mode, JavaScript integration, and design token systems, see our CSS Custom Properties Complete Guide.

color-mix() — Modern Color Mixing

The color-mix() function blends two colors in a specified color space. It replaces the need for pre-calculated color shades and enables dynamic color relationships in pure CSS.

Basic Syntax

/* Mix 50/50 in srgb (default proportions) */
.blended {
    color: color-mix(in srgb, blue, white);
}

/* Custom proportions */
.light-primary {
    background: color-mix(in srgb, var(--color-primary) 20%, white);
}

.dark-primary {
    background: color-mix(in srgb, var(--color-primary) 80%, black);
}

Color Spaces Matter

/* srgb — familiar, but can produce muddy mid-tones */
.mix-srgb {
    background: color-mix(in srgb, blue 50%, yellow 50%);  /* grayish */
}

/* oklch — perceptually uniform, produces vibrant mixes */
.mix-oklch {
    background: color-mix(in oklch, blue 50%, yellow 50%);  /* vibrant green */
}

/* oklab — perceptually uniform, good for tints and shades */
.mix-oklab {
    background: color-mix(in oklab, #3b82f6 70%, white 30%);
}

Practical Patterns

/* Generate a full shade palette from a single color */
:root {
    --brand: #3b82f6;
    --brand-50:  color-mix(in oklch, var(--brand) 5%, white);
    --brand-100: color-mix(in oklch, var(--brand) 15%, white);
    --brand-200: color-mix(in oklch, var(--brand) 30%, white);
    --brand-300: color-mix(in oklch, var(--brand) 50%, white);
    --brand-400: color-mix(in oklch, var(--brand) 75%, white);
    --brand-500: var(--brand);
    --brand-600: color-mix(in oklch, var(--brand) 85%, black);
    --brand-700: color-mix(in oklch, var(--brand) 70%, black);
    --brand-800: color-mix(in oklch, var(--brand) 50%, black);
    --brand-900: color-mix(in oklch, var(--brand) 30%, black);
}

/* Hover state: darken by mixing with black */
.button {
    background: var(--brand);
}
.button:hover {
    background: color-mix(in oklch, var(--brand) 85%, black);
}

/* Semi-transparent overlay without opacity */
.overlay {
    background: color-mix(in srgb, var(--brand) 40%, transparent);
}

/* Accessible focus ring that works on any background */
.focused {
    outline: 3px solid color-mix(in srgb, var(--brand) 60%, transparent);
    outline-offset: 2px;
}

The oklch color space generally produces the most visually pleasing mixes because it is perceptually uniform — meaning equal numerical changes create equal perceived changes in lightness and chroma.

env() — Environment Variables

The env() function reads values set by the browser or operating system, not by your CSS. The most important use case is handling safe area insets on devices with notches, rounded corners, or dynamic toolbars.

/* Enable full viewport coverage — required for env() to work */
/* In your HTML: <meta name="viewport" content="..., viewport-fit=cover"> */

/* Ensure content avoids the notch and home indicator */
body {
    padding-top: env(safe-area-inset-top);
    padding-right: env(safe-area-inset-right);
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left);
}

/* With fallback values (second argument) */
.fixed-nav {
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: env(safe-area-inset-left, 0px);
    padding-right: env(safe-area-inset-right, 0px);
}

/* Combining with calc() for additional spacing */
.bottom-bar {
    padding-bottom: calc(env(safe-area-inset-bottom) + 1rem);
    height: calc(60px + env(safe-area-inset-bottom));
}

/* Fixed bottom navigation on notched devices */
.tab-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem env(safe-area-inset-right) calc(0.5rem + env(safe-area-inset-bottom)) env(safe-area-inset-left);
}

The env() function is essential for progressive web apps (PWAs) that run in standalone mode on mobile devices. Without safe area handling, content can be hidden behind the device notch or obscured by the home indicator bar.

minmax() — Grid Track Sizing

The minmax() function defines a size range for grid tracks. It is only valid inside grid-template-columns, grid-template-rows, and related grid properties.

/* Columns that are at least 200px but grow to fill space */
.grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(200px, 1fr));
    gap: 1rem;
}

/* Sidebar layout: fixed minimum sidebar, flexible main */
.layout {
    display: grid;
    grid-template-columns: minmax(250px, 300px) minmax(0, 1fr);
    gap: 2rem;
}

/* Rows with minimum height */
.dashboard {
    display: grid;
    grid-template-rows: minmax(60px, auto) minmax(400px, 1fr) minmax(40px, auto);
}

/* Responsive card grid that never overflows */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: 1.5rem;
}

The last example combines minmax(), min(), repeat(), and auto-fill to create a grid that adapts from a single column on small screens to as many columns as will fit on large screens — with no media queries. The min(280px, 100%) ensures the minimum value never exceeds the container width.

repeat() — Grid Patterns

The repeat() function avoids writing the same track size multiple times. It works with fixed counts and the automatic keywords auto-fill and auto-fit.

/* Fixed column count */
.grid-4 {
    grid-template-columns: repeat(4, 1fr);
}

/* Equivalent to writing it out */
.grid-4-verbose {
    grid-template-columns: 1fr 1fr 1fr 1fr;
}

/* Repeating a pattern */
.alternating {
    grid-template-columns: repeat(3, 1fr 2fr);
    /* Produces: 1fr 2fr 1fr 2fr 1fr 2fr — 6 columns */
}

/* auto-fill: creates as many tracks as fit, even if empty */
.auto-fill-grid {
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

/* auto-fit: same as auto-fill, but collapses empty tracks */
.auto-fit-grid {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* Difference: with 2 items in a wide container:
   auto-fill: [item] [item] [empty] [empty]  — empty tracks take space
   auto-fit:  [item          ] [item         ]  — items stretch to fill */

For a deep dive into CSS Grid including template areas, alignment, and complex layout patterns, see our CSS Grid Complete Guide.

attr() — Reading HTML Attributes

The attr() function reads the value of an HTML attribute. Historically limited to the content property, the CSS Values Level 5 spec expands it to work with any property and typed values.

/* Classic usage: displaying attribute values in content */
a[href^="http"]::after {
    content: " (" attr(href) ")";
}

/* Tooltip from data attribute */
[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    background: #1f2937;
    color: white;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.85rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
}

[data-tooltip]:hover::after {
    opacity: 1;
}

/* Print stylesheet: show URLs */
@media print {
    a[href]::after {
        content: " [" attr(href) "]";
        font-size: 0.8em;
        color: #666;
    }
}

/* Display data attribute values as labels */
.progress-bar::after {
    content: attr(data-percent) "%";
}

/* Typed attr() — CSS Values Level 5 (limited browser support in 2026) */
/* .bar { width: attr(data-width px, 100px); } */
/* .colored { color: attr(data-color color, black); } */

As of 2026, the typed version of attr() (using it for properties other than content) has limited browser support. The content property usage works everywhere. For dynamic styling based on attributes, CSS custom properties set via JavaScript remain the more practical approach.

url() — Resource References

The url() function references external resources: images, fonts, stylesheets, and other files.

/* Background images */
.hero {
    background-image: url('/images/hero-bg.webp');
    background-size: cover;
}

/* Multiple backgrounds */
.layered {
    background:
        url('/images/pattern.svg') repeat,
        url('/images/gradient.webp') center / cover no-repeat;
}

/* Custom fonts */
@font-face {
    font-family: 'CustomFont';
    src: url('/fonts/custom.woff2') format('woff2'),
         url('/fonts/custom.woff') format('woff');
    font-display: swap;
}

/* Cursor */
.custom-cursor {
    cursor: url('/images/cursor.png') 4 4, pointer;
}

/* List markers */
ul.check {
    list-style-image: url('/images/check.svg');
}

/* CSS masks */
.masked {
    mask-image: url('/images/mask-shape.svg');
    -webkit-mask-image: url('/images/mask-shape.svg');
}

/* url() with custom properties */
:root {
    --bg-image: url('/images/default-bg.webp');
}
.section {
    background-image: var(--bg-image);
}

Note that url() values cannot be constructed by concatenation inside var(). Writing url(var(--base-path) + 'image.png') will not work. Instead, store the entire url() call in the custom property as shown above.

Modern CSS Math Functions

CSS now includes a full suite of mathematical functions that previously required JavaScript or preprocessor calculations. These shipped across all major browsers in 2024-2025 and are safe for production in 2026.

round(), mod(), and rem() — Stepped Values

/* round() — round to the nearest step */
.snapped {
    /* Round font size to nearest 2px for consistent rendering */
    font-size: round(2.3rem, 1px);         /* rounds to nearest 1px */
    width: round(nearest, 33.33%, 10%);     /* rounds to nearest 10% → 30% */
}

/* Rounding strategies */
.strategies {
    width: round(up, 65%, 10%);      /* round up → 70% */
    width: round(down, 65%, 10%);    /* round down → 60% */
    width: round(nearest, 65%, 10%); /* round nearest → 70% */
    width: round(to-zero, -65%, 10%); /* toward zero → -60% */
}

/* Snap grid items to a baseline grid */
.baseline-grid {
    --baseline: 8px;
    padding: round(1.3rem, var(--baseline));
    margin-bottom: round(nearest, 1em, var(--baseline));
}

/* mod() — remainder with the sign of the divisor */
.mod-example {
    /* Cycle through values: useful for alternating patterns */
    --cycle: mod(var(--index), 3);
}

/* rem() — remainder with the sign of the dividend */
.rem-example {
    --remainder: rem(var(--value), 100);
}

The difference between mod() and rem() only matters with negative numbers. mod(-7, 3) returns 2 (sign of divisor), while rem(-7, 3) returns -1 (sign of dividend). For positive values, they produce identical results.

abs() and sign() — Sign-Related Functions

/* abs() — absolute value */
.distance {
    /* Always positive, regardless of which direction */
    --offset: calc(var(--mouse-x) - 50%);
    transform: translateX(abs(var(--offset)));
}

/* sign() — returns -1, 0, or 1 */
.direction {
    --delta: calc(var(--current) - var(--target));
    /* sign() tells you the direction without the magnitude */
    transform: scaleX(sign(var(--delta)));
}

/* Practical: flip an arrow based on scroll direction */
.scroll-indicator {
    --scroll-dir: sign(var(--scroll-delta));
    transform: rotate(calc(90deg * var(--scroll-dir)));
}

Trigonometric Functions: sin(), cos(), tan()

Trigonometric functions enable circular layouts, wave patterns, and smooth mathematical curves in pure CSS.

/* Circular layout — position items around a circle */
.circle-layout {
    --items: 8;
    --radius: 150px;
    position: relative;
    width: calc(var(--radius) * 2);
    height: calc(var(--radius) * 2);
}

.circle-layout > * {
    position: absolute;
    --angle: calc(360deg / var(--items) * var(--i));
    left: calc(50% + var(--radius) * cos(var(--angle)) - 20px);
    top: calc(50% + var(--radius) * sin(var(--angle)) - 20px);
}

/* In HTML, each item gets: style="--i: 0", style="--i: 1", etc. */

/* Wave pattern using @property for animation */
@property --wave-offset {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

.wave-item {
    --wave-offset: 0deg;
    --phase: calc(var(--i) * 45deg);
    transform: translateY(calc(sin(var(--wave-offset) + var(--phase)) * 20px));
    animation: wave 2s ease-in-out infinite;
}

@keyframes wave {
    to { --wave-offset: 360deg; }
}

/* Clock hands */
.clock-hand {
    --angle: calc(var(--hours, 0) * 30deg);  /* 360 / 12 = 30deg per hour */
    transform: rotate(var(--angle));
}

/* Pendulum motion */
.pendulum {
    --swing: calc(sin(var(--time)) * 30deg);
    transform-origin: top center;
    transform: rotate(var(--swing));
}

Exponential Functions: pow(), sqrt(), log(), exp()

/* pow() — raise to a power */
/* Exponential type scale */
:root {
    --base-size: 1rem;
    --ratio: 1.25;
    --step-0: var(--base-size);
    --step-1: calc(var(--base-size) * pow(var(--ratio), 1));  /* 1.25rem */
    --step-2: calc(var(--base-size) * pow(var(--ratio), 2));  /* 1.5625rem */
    --step-3: calc(var(--base-size) * pow(var(--ratio), 3));  /* 1.953rem */
    --step-4: calc(var(--base-size) * pow(var(--ratio), 4));  /* 2.441rem */
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }
body { font-size: var(--step-0); }

/* sqrt() — square root */
.proportional {
    /* Scale an element proportionally to area rather than linearly */
    --scale: sqrt(var(--data-value));
    width: calc(var(--scale) * 1px);
    height: calc(var(--scale) * 1px);
}

/* Easing with sqrt — fast start, slow end */
.progress-fill {
    width: calc(sqrt(var(--progress) / 100) * 100%);
}

/* log() — logarithm */
.log-scale {
    /* Logarithmic scale for data visualization */
    --bar-width: calc(log(var(--value)) / log(1000) * 100%);
    width: var(--bar-width);
}

/* exp() — e raised to a power */
.exponential-growth {
    --growth: calc(exp(var(--t)) * 1px);
    height: var(--growth);
}

Inverse Trigonometric: asin(), acos(), atan(), atan2()

/* atan2() — angle between two points */
.pointer {
    /* Point toward a target using mouse coordinates */
    --dx: calc(var(--target-x) - var(--origin-x));
    --dy: calc(var(--target-y) - var(--origin-y));
    transform: rotate(atan2(var(--dy), var(--dx)));
}

/* Calculate angle from aspect ratio */
.diagonal {
    --angle: atan2(var(--height), var(--width));
    transform: rotate(var(--angle));
}

/* acos for angle from dot product (advanced geometry) */
.angle-display::after {
    --angle-deg: calc(acos(var(--cos-value)) * 180 / 3.14159);
    content: "Angle: " counter(angle) "deg";
    counter-reset: angle var(--angle-deg);
}

Nesting Functions Together

The real power of CSS functions emerges when you combine them. Every function can be nested inside any other where the types are compatible.

/* Fluid container with precise constraints */
.container {
    width: clamp(320px, calc(100% - var(--sidebar-width, 0px)), 1200px);
    padding-inline: max(1rem, env(safe-area-inset-left));
}

/* Responsive grid with snapped column widths */
.grid {
    grid-template-columns: repeat(
        auto-fill,
        minmax(min(round(nearest, 25%, 1px), 100%), 1fr)
    );
}

/* Color that adapts to a custom property with fallback mixing */
.adaptive {
    background: color-mix(
        in oklch,
        var(--surface-color, #1f2937) 90%,
        var(--accent-color, #3b82f6)
    );
}

/* Circular positioning with fluid radius */
.orbit-item {
    --radius: clamp(80px, 15vw, 200px);
    --angle: calc(360deg / var(--total) * var(--i));
    left: calc(50% + var(--radius) * cos(var(--angle)));
    top: calc(50% + var(--radius) * sin(var(--angle)));
}

/* Type scale that respects user preferences */
h1 {
    font-size: clamp(
        calc(var(--base-size) * pow(var(--ratio), 2)),
        calc(var(--base-size) * pow(var(--ratio), 2) + 1.5vw),
        calc(var(--base-size) * pow(var(--ratio), 4))
    );
}

Browser Support Summary (2026)

Here is the current browser support status for every CSS function covered in this guide:

All functions in this guide are safe for production use in 2026. For the newest math functions, consider providing a static fallback for the small percentage of users on older browsers:

/* Fallback pattern for newer math functions */
.element {
    /* Fallback for browsers without round() */
    font-size: 1.5rem;
    font-size: round(1.53rem, 0.125rem);
}

/* @supports for feature detection */
@supports (width: round(1px, 1px)) {
    .snapped {
        padding: round(1.3rem, var(--baseline));
    }
}

Quick Reference

A compact summary of every CSS function, its purpose, and typical usage:

/* ARITHMETIC */
calc(100% - 2rem)                    /* Mix units, basic math */

/* COMPARISON */
min(300px, 100%)                     /* Smallest value wins */
max(44px, 3rem)                      /* Largest value wins */
clamp(1rem, 3vw, 2rem)              /* Value with floor and ceiling */

/* CUSTOM PROPERTIES */
var(--name)                          /* Read custom property */
var(--name, fallback)                /* With fallback value */

/* COLOR */
color-mix(in oklch, blue 60%, red)   /* Blend two colors */

/* ENVIRONMENT */
env(safe-area-inset-bottom)          /* Device safe areas */
env(safe-area-inset-top, 0px)       /* With fallback */

/* GRID */
minmax(200px, 1fr)                   /* Track size range */
repeat(3, 1fr)                       /* Repeat track pattern */
repeat(auto-fill, minmax(200px, 1fr)) /* Auto-responsive grid */

/* RESOURCES */
url('/path/to/file.png')             /* External resource */
attr(data-label)                     /* HTML attribute value */

/* ROUNDING */
round(nearest, 1.5rem, 0.25rem)     /* Round to step */
mod(7, 3)                           /* Modulo (sign of divisor) */
rem(7, 3)                           /* Remainder (sign of dividend) */

/* SIGN */
abs(-5px)                            /* Absolute value → 5px */
sign(-5px)                           /* Sign → -1 */

/* TRIGONOMETRY */
sin(45deg)                           /* Sine → 0.707 */
cos(45deg)                           /* Cosine → 0.707 */
tan(45deg)                           /* Tangent → 1 */
asin(0.5)                           /* Inverse sine → 30deg */
acos(0.5)                           /* Inverse cosine → 60deg */
atan(1)                             /* Inverse tangent → 45deg */
atan2(3, 4)                         /* Two-argument arctangent */

/* EXPONENTIAL */
pow(2, 3)                           /* Power → 8 */
sqrt(16)                            /* Square root → 4 */
log(100)                            /* Natural log */
exp(1)                              /* e^1 → 2.718 */

Frequently Asked Questions

What is the difference between calc(), min(), max(), and clamp() in CSS?

calc() performs arithmetic operations (addition, subtraction, multiplication, division) and can mix different units like px, %, rem, and vw. min() returns the smallest value from a comma-separated list. max() returns the largest value. clamp() takes three arguments (minimum, preferred, maximum) and returns the preferred value constrained between the minimum and maximum. For example, clamp(1rem, 2.5vw, 2rem) gives you a value that is at least 1rem, at most 2rem, and ideally 2.5vw. All four functions can be nested inside each other for complex responsive calculations.

Can I use CSS math functions like round(), sin(), and cos() in production?

Yes. As of 2026, the CSS trigonometric functions (sin(), cos(), tan(), asin(), acos(), atan(), atan2()), exponential functions (pow(), sqrt(), log(), exp()), stepped value functions (round(), mod(), rem()), and sign-related functions (abs(), sign()) are supported in all major browsers. These functions enable complex mathematical calculations directly in CSS without JavaScript, such as circular layouts, wave patterns, and precise rounding.

How does color-mix() work and what color spaces does it support?

color-mix() blends two colors together in a specified color space. The syntax is color-mix(in <color-space>, color1 percentage, color2 percentage). Supported color spaces include srgb, srgb-linear, lab, lch, oklch, oklab, xyz, hsl, and hwb. The oklch and oklab spaces generally produce the most visually pleasing results because they are perceptually uniform, meaning equal mathematical changes correspond to equal perceived changes in color.

What is the env() function used for in CSS?

The env() function accesses environment variables defined by the browser or device, most commonly the safe area insets on devices with non-rectangular screens like iPhones with a notch or Dynamic Island. The four standard values are env(safe-area-inset-top), env(safe-area-inset-right), env(safe-area-inset-bottom), and env(safe-area-inset-left). To enable them, add viewport-fit=cover to your viewport meta tag. Unlike var(), env() values cannot be set by the developer; they come from the user agent.

Can I nest CSS functions inside each other?

Yes, CSS functions can be nested freely. For example, width: min(calc(100% - 2rem), 800px) gives a fluid width capped at 800px. You can use var() inside calc(), clamp() inside var() fallbacks, min() inside grid-template-columns, and nest math functions like round(calc(var(--size) * 1.5), 1px). The only constraint is that the final resolved value must be valid for the property you are setting.

Summary

CSS functions have evolved from a handful of utilities into a comprehensive computational toolkit. Here is what to take away from this guide:

  1. calc() is foundational. Use it whenever you need to mix units or do arithmetic in property values. Remember the spaces around + and -.
  2. min(), max(), and clamp() replace most responsive-sizing media queries with single declarations. clamp() is the go-to for fluid typography and spacing.
  3. var() connects everything to your custom property system, enabling theming, component variants, and JavaScript bridges.
  4. color-mix() generates dynamic color relationships from a single brand color. Prefer the oklch color space for perceptually uniform mixing.
  5. env() is required for proper safe-area handling on modern mobile devices, especially for PWAs.
  6. minmax() and repeat() are the backbone of responsive CSS Grid layouts, especially combined with auto-fill/auto-fit.
  7. The new math functions (round, mod, sin, cos, pow, sqrt, abs, sign, and more) bring full mathematical computation to CSS. Use them for type scales, circular layouts, data visualization, and precise rounding.
  8. Functions nest freely. Combining clamp(), calc(), var(), and min() in a single declaration is perfectly valid and often the cleanest solution.

For related CSS guides, explore our CSS Custom Properties Guide for deep coverage of the var() ecosystem, the CSS Grid Guide for layout patterns using minmax() and repeat(), and the CSS Gradients Guide for visual effects that combine many of these functions. Check our CSS Cheat Sheet for a quick-reference companion to this guide.

Related Resources

CSS Gradient Generator
Build gradients using CSS functions visually
CSS Custom Properties Guide
Deep dive into var() and custom properties
CSS Grid Complete Guide
Master minmax(), repeat(), and grid layouts
CSS Cheat Sheet
Quick reference for all CSS properties and functions