CSS Functions: calc(), min(), max(), clamp()
CSS has several very powerful calculation functions — they let you do math operations directly in CSS without JavaScript. These functions can combine different units (pixels, percentages, rem, vw) in a single calculation.
Main functions covered:
- calc() — basic arithmetic operations (+, -, *, /) with mixed units
- min() — picks the smallest value from several values
- max() — picks the largest value from several values
- clamp() — constrains a value between a minimum, preferred, and maximum
- var() — review of using CSS Variables inside functions
- attr() — using HTML attribute values as CSS values
- counter() — counting and displaying sequential numbers
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Functions: calc, min, max, clamp</title>
<style>
:root {
--primary: #667eea;
--secondary: #764ba2;
--space-unit: 8px;
--max-width: 1200px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f0f2f5;
color: #333;
line-height: 1.6;
}
/* ===== Fluid Typography with clamp() ===== */
h1 {
font-size: clamp(1.8rem, 5vw, 3.5rem);
font-weight: 800;
color: #1a1a2e;
text-align: center;
margin-bottom: 10px;
}
.subtitle {
text-align: center;
color: #888;
font-size: clamp(0.9rem, 2vw, 1.1rem);
margin-bottom: 50px;
}
.container {
width: min(90%, var(--max-width));
margin: 0 auto;
padding: 0 20px;
}
/* ===== Section Styles ===== */
.section {
margin-bottom: 60px;
}
.section-header {
text-align: center;
margin-bottom: 30px;
}
.section-header h2 {
font-size: clamp(1.3rem, 3vw, 1.8rem);
color: #1a1a2e;
margin-bottom: 5px;
}
.section-header p {
color: #888;
font-size: 0.9rem;
}
/* ===== calc() Examples ===== */
.calc-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 25px;
}
.calc-card {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.calc-card h3 {
color: var(--primary);
font-size: 0.9rem;
margin-bottom: 10px;
font-family: monospace;
}
.calc-card p {
color: #666;
font-size: 0.85rem;
margin-bottom: 15px;
}
.calc-demo {
background: #f8f9fa;
border-radius: 8px;
padding: 15px;
}
/* calc: width minus padding */
.calc-box-1 {
width: calc(100% - 40px);
background: var(--primary);
color: white;
padding: 10px;
border-radius: 6px;
text-align: center;
font-size: 0.8rem;
}
/* calc: mixing units */
.calc-box-2 {
width: calc(100% - 2rem);
background: var(--secondary);
color: white;
padding: 10px;
border-radius: 6px;
text-align: center;
font-size: 0.8rem;
}
/* calc: viewport minus fixed */
.calc-box-3 {
width: calc(100vw - 80px);
max-width: 100%;
background: #f5576c;
color: white;
padding: 10px;
border-radius: 6px;
text-align: center;
font-size: 0.8rem;
}
/* calc: multi-step */
.calc-box-4 {
width: calc((100% - 60px) / 3);
min-width: 80px;
background: #43e97b;
color: #1a1a2e;
padding: 10px;
border-radius: 6px;
text-align: center;
font-size: 0.8rem;
font-weight: 600;
}
.calc-row {
display: flex;
gap: 20px;
flex-wrap: wrap;
}
/* ===== min() Examples ===== */
.min-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 25px;
}
.min-card {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.min-card h3 {
color: var(--primary);
font-size: 0.9rem;
margin-bottom: 10px;
font-family: monospace;
}
.min-card p {
color: #666;
font-size: 0.85rem;
margin-bottom: 15px;
}
/* min: never exceed max-width */
.min-box-1 {
width: min(100%, 600px);
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
padding: 15px;
border-radius: 8px;
text-align: center;
font-size: 0.8rem;
}
/* min: font size */
.min-box-2 {
font-size: min(5vw, 24px);
background: #f5576c;
color: white;
padding: 15px;
border-radius: 8px;
text-align: center;
}
/* min: spacing */
.min-box-3 {
padding: min(5vw, 30px);
background: #43e97b;
color: #1a1a2e;
border-radius: 8px;
text-align: center;
font-size: 0.8rem;
font-weight: 600;
}
/* ===== max() Examples ===== */
.max-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 25px;
}
.max-card {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.max-card h3 {
color: var(--primary);
font-size: 0.9rem;
margin-bottom: 10px;
font-family: monospace;
}
.max-card p {
color: #666;
font-size: 0.85rem;
margin-bottom: 15px;
}
/* max: never go below min */
.max-box-1 {
width: max(50%, 300px);
background: linear-gradient(135deg, #f5576c, #ff6b6b);
color: white;
padding: 15px;
border-radius: 8px;
text-align: center;
font-size: 0.8rem;
}
/* max: minimum font size */
.max-box-2 {
font-size: max(16px, 1.2vw);
background: #667eea;
color: white;
padding: 15px;
border-radius: 8px;
text-align: center;
}
/* max: minimum spacing */
.max-box-3 {
padding: max(20px, 3vw);
background: #fa709a;
color: white;
border-radius: 8px;
text-align: center;
font-size: 0.8rem;
}
/* ===== clamp() Section ===== */
.clamp-section {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.clamp-visual {
display: flex;
gap: 20px;
align-items: stretch;
margin-bottom: 30px;
}
.clamp-label-box {
flex: 0 0 auto;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
padding: 15px 20px;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.clamp-label-box .label {
font-size: 0.7rem;
opacity: 0.8;
margin-bottom: 5px;
}
.clamp-label-box .value {
font-size: 1.5rem;
font-weight: bold;
font-family: monospace;
}
.clamp-content {
flex: 1;
}
.clamp-content h3 {
color: #1a1a2e;
margin-bottom: 10px;
font-size: clamp(1.2rem, 3vw, 1.6rem);
}
.clamp-content p {
color: #666;
font-size: clamp(0.85rem, 1.8vw, 1rem);
line-height: 1.7;
}
.clamp-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 30px;
}
.clamp-example {
background: #f8f9fa;
border-radius: 10px;
padding: 20px;
}
.clamp-example h4 {
font-family: monospace;
font-size: 0.8rem;
color: var(--primary);
margin-bottom: 8px;
}
.clamp-example .demo {
background: var(--primary);
color: white;
padding: 12px;
border-radius: 6px;
text-align: center;
font-size: 0.8rem;
}
/* ===== var() Review ===== */
.var-review {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 25px;
}
.var-card {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.var-card h3 {
color: var(--primary);
font-size: 0.9rem;
margin-bottom: 12px;
font-family: monospace;
}
.var-card code {
display: block;
background: #1a1a2e;
color: #e0e0e0;
padding: 15px;
border-radius: 8px;
font-size: 0.8rem;
line-height: 1.6;
overflow-x: auto;
}
/* ===== Practical: Responsive Spacing ===== */
.spacing-demo {
background: white;
border-radius: 12px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.spacing-row {
display: flex;
gap: 15px;
margin-bottom: 15px;
flex-wrap: wrap;
}
.spacing-item {
flex: 1;
min-width: 100px;
background: linear-gradient(135deg, rgba(102,126,234,0.1), rgba(118,75,162,0.1));
border: 1px solid rgba(102,126,234,0.2);
border-radius: 8px;
padding: clamp(10px, 2vw, 20px);
text-align: center;
}
.spacing-item .label {
font-size: 0.7rem;
color: #888;
font-family: monospace;
margin-bottom: 5px;
}
.spacing-item .size {
font-size: 0.85rem;
color: var(--primary);
font-weight: 600;
}
/* ===== Practical: Dynamic Widths ===== */
.dynamic-demo {
background: white;
border-radius: 12px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
margin-top: 25px;
}
.dyn-row {
display: flex;
gap: 15px;
margin-bottom: 20px;
align-items: center;
}
.dyn-label {
flex: 0 0 200px;
font-family: monospace;
font-size: 0.8rem;
color: #666;
}
.dyn-bar {
flex: 1;
height: 30px;
background: #f0f2f5;
border-radius: 6px;
overflow: hidden;
}
.dyn-fill {
height: 100%;
border-radius: 6px;
display: flex;
align-items: center;
padding-left: 10px;
font-size: 0.7rem;
color: white;
font-weight: 600;
}
.dyn-fill-1 {
width: calc(100% - 40px);
background: var(--primary);
}
.dyn-fill-2 {
width: min(80%, 400px);
background: var(--secondary);
}
.dyn-fill-3 {
width: max(30%, 200px);
background: #f5576c;
}
.dyn-fill-4 {
width: clamp(100px, 50%, 500px);
background: #43e97b;
color: #1a1a2e;
}
/* ===== Practical: Full Responsive Page ===== */
.resp-demo {
margin-top: 25px;
}
.resp-header {
background: linear-gradient(135deg, #1a1a2e, #16213e);
color: white;
padding: clamp(30px, 5vw, 60px) clamp(20px, 4vw, 40px);
border-radius: 12px 12px 0 0;
text-align: center;
}
.resp-header h2 {
font-size: clamp(1.5rem, 4vw, 2.5rem);
margin-bottom: 10px;
}
.resp-header p {
color: #aaa;
font-size: clamp(0.85rem, 2vw, 1rem);
}
.resp-body {
background: white;
padding: clamp(20px, 3vw, 40px);
border-radius: 0 0 12px 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.resp-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
gap: clamp(15px, 2vw, 25px);
}
.resp-item {
background: #f8f9fa;
border-radius: 10px;
padding: clamp(15px, 2vw, 25px);
text-align: center;
}
.resp-item-icon {
font-size: 2rem;
margin-bottom: 10px;
}
.resp-item h4 {
font-size: clamp(0.9rem, 1.5vw, 1.1rem);
margin-bottom: 5px;
color: #1a1a2e;
}
.resp-item p {
font-size: clamp(0.8rem, 1.2vw, 0.85rem);
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>CSS Functions: calc, min, max, clamp</h1>
<p class="subtitle">Dynamic calculations directly in CSS — no JavaScript needed</p>
<div class="section">
<div class="section-header">
<h2>calc() — Mixed Unit Arithmetic</h2>
<p>+ , -, *, / operations with different units in a single calculation</p>
</div>
<div class="calc-grid">
<div class="calc-card">
<h3>width: calc(100% - 40px)</h3>
<p>100% of parent width minus 20px padding on each side</p>
<div class="calc-demo">
<div class="calc-box-1">calc(100% - 40px)</div>
</div>
</div>
<div class="calc-card">
<h3>width: calc(100% - 2rem)</h3>
<p>Combining percentage and rem — impossible without calc</p>
<div class="calc-demo">
<div class="calc-box-2">calc(100% - 2rem)</div>
</div>
</div>
<div class="calc-card">
<h3>width: calc(100vw - 80px)</h3>
<p>Viewport width minus left-right margins</p>
<div class="calc-demo">
<div class="calc-box-3">calc(100vw - 80px)</div>
</div>
</div>
<div class="calc-card">
<h3>width: calc((100% - 60px) / 3)</h3>
<p>3 columns with a 20px gap — one row without flexbox</p>
<div class="calc-demo">
<div class="calc-row">
<div class="calc-box-4">1/3</div>
<div class="calc-box-4">1/3</div>
<div class="calc-box-4">1/3</div>
</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>min() — Pick the Smallest Value</h2>
<p>Maximum limit: use the smallest value among the options</p>
</div>
<div class="min-grid">
<div class="min-card">
<h3>width: min(100%, 600px)</h3>
<p>Maximum width of 600px, does not exceed the parent. Perfect for containers.</p>
<div class="calc-demo">
<div class="min-box-1">min(100%, 600px) — try resizing</div>
</div>
</div>
<div class="min-card">
<h3>font-size: min(5vw, 24px)</h3>
<p>Font scales with the viewport but never exceeds 24px.</p>
<div class="calc-demo">
<div class="min-box-2">min(5vw, 24px) — font responsive</div>
</div>
</div>
<div class="min-card">
<h3>padding: min(5vw, 30px)</h3>
<p>Proportional padding but with a maximum limit.</p>
<div class="calc-demo">
<div class="min-box-3">min(5vw, 30px) — padding responsive</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>max() — Pick the Largest Value</h2>
<p>Minimum limit: use the largest value among the options</p>
</div>
<div class="max-grid">
<div class="max-card">
<h3>width: max(50%, 300px)</h3>
<p>Minimum width of 300px, but never less than 50% of the parent.</p>
<div class="calc-demo">
<div class="max-box-1">max(50%, 300px) — resize to see</div>
</div>
</div>
<div class="max-card">
<h3>font-size: max(16px, 1.2vw)</h3>
<p>Font never goes below 16px, but can still scale.</p>
<div class="calc-demo">
<div class="max-box-2">max(16px, 1.2vw) — minimum font</div>
</div>
</div>
<div class="max-card">
<h3>padding: max(20px, 3vw)</h3>
<p>Padding never goes below 20px.</p>
<div class="calc-demo">
<div class="max-box-3">max(20px, 3vw) — minimum padding</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="clamp-section">
<div class="section-header">
<h2>clamp() — Bounded Values (min, preferred, max)</h2>
<p>clamp(minimum, preferred, maximum) — bound a value to a specific range</p>
</div>
<div class="clamp-visual">
<div class="clamp-label-box">
<span class="label">min</span>
<span class="value">1.5rem</span>
</div>
<div class="clamp-content">
<h3>clamp(1.5rem, 4vw, 3rem)</h3>
<p>This font will scale between 1.5rem (minimum) and 3rem (maximum), with a preferred value of 4vw. Notice how the text size changes as you resize the browser — no media queries needed!</p>
</div>
<div class="clamp-label-box">
<span class="label">max</span>
<span class="value">3rem</span>
</div>
</div>
<div class="clamp-grid">
<div class="clamp-example">
<h4>font-size: clamp(1rem, 2.5vw, 2rem)</h4>
<div class="demo" style="font-size: clamp(1rem, 2.5vw, 2rem);">
Responsive Typography
</div>
</div>
<div class="clamp-example">
<h4>padding: clamp(15px, 3vw, 40px)</h4>
<div class="demo" style="padding: clamp(15px, 3vw, 40px);">
Responsive Padding
</div>
</div>
<div class="clamp-example">
<h4>width: clamp(200px, 50%, 600px)</h4>
<div class="demo" style="width: clamp(200px, 50%, 600px); margin: 0 auto;">
Responsive Width
</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>var() — Review CSS Variables</h2>
<p>Dynamic values that can be changed and given a fallback</p>
</div>
<div class="var-review">
<div class="var-card">
<h3>Basic Usage</h3>
<code>
:root { --color: #667eea; }
.box {
background: var(--color);
}
</code>
</div>
<div class="var-card">
<h3>With Fallback</h3>
<code>
.box {
color: var(--text, #333);
/* #333 if --text does not exist */
}
</code>
</div>
<div class="var-card">
<h3>Inside calc()</h3>
<code>
:root { --unit: 8px; }
.box {
padding: calc(var(--unit) * 3);
/* 24px */
}
</code>
</div>
<div class="var-card">
<h3>Dynamic via JS</h3>
<code>
// Change the variable
el.style.setProperty(
'--color', '#f5576c'
);
// Read the variable
getComputedStyle(el)
.getPropertyValue('--color');
</code>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>Practice: Responsive Spacing</h2>
<p>Spacing that adapts to screen size using clamp()</p>
</div>
<div class="spacing-demo">
<div class="spacing-row">
<div class="spacing-item">
<div class="label">clamp(10px, 2vw, 20px)</div>
<div class="size">Responsive</div>
</div>
<div class="spacing-item">
<div class="label">clamp(10px, 2vw, 20px)</div>
<div class="size">Responsive</div>
</div>
<div class="spacing-item">
<div class="label">clamp(10px, 2vw, 20px)</div>
<div class="size">Responsive</div>
</div>
<div class="spacing-item">
<div class="label">clamp(10px, 2vw, 20px)</div>
<div class="size">Responsive</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>Praktik: Dynamic Width Calculations</h2>
</div>
<div class="dynamic-demo">
<div class="dyn-row">
<div class="dyn-label">calc(100% - 40px)</div>
<div class="dyn-bar">
<div class="dyn-fill dyn-fill-1"></div>
</div>
</div>
<div class="dyn-row">
<div class="dyn-label">min(80%, 400px)</div>
<div class="dyn-bar">
<div class="dyn-fill dyn-fill-2"></div>
</div>
</div>
<div class="dyn-row">
<div class="dyn-label">max(30%, 200px)</div>
<div class="dyn-bar">
<div class="dyn-fill dyn-fill-3"></div>
</div>
</div>
<div class="dyn-row">
<div class="dyn-label">clamp(100px, 50%, 500px)</div>
<div class="dyn-bar">
<div class="dyn-fill dyn-fill-4"></div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header">
<h2>Practice: Complete Responsive Page</h2>
<p>All CSS functions combined for a fully fluid page</p>
</div>
<div class="resp-demo">
<div class="resp-header">
<h2>All Fluid Without Media Queries</h2>
<p>Resize the browser to see all elements adapt</p>
</div>
<div class="resp-body">
<div class="resp-grid">
<div class="resp-item">
<div class="resp-item-icon">📐</div>
<h4>clamp() Typography</h4>
<p>Font scales with the viewport</p>
</div>
<div class="resp-item">
<div class="resp-item-icon">↔️</div>
<h4>min() Container</h4>
<p>Width automatically limited</p>
</div>
<div class="resp-item">
<div class="resp-item-icon">📏</div>
<h4>calc() Spacing</h4>
<p>Padding from mixed units</p>
</div>
<div class="resp-item">
<div class="resp-item-icon">🎯</div>
<h4>max() Minimum</h4>
<p>Consistent lower bound</p>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Code Explanation
calc()
calc() enables arithmetic operations with different units — something that was not possible before CSS Variables and calculation functions.
Supported operators: + (addition), - (subtraction), * (multiplication), / (division)
/* Important: spaces are required around + and - */
.box {
width: calc(100% - 40px); /* correct */
width: calc(100%-40px); /* wrong */
width: calc(100% / 3); /* division — spaces optional */
width: calc((100% - 60px) / 3); /* parentheses for order of operations */
}
Examples of using calc:
/* Container with padding */
.container {
width: calc(100% - 40px); /* 20px padding left-right */
max-width: calc(100vw - 80px); /* viewport minus margins */
}
/* Sidebar layout */
.sidebar { width: 250px; }
.main { width: calc(100% - 250px - 30px); } /* minus sidebar + gap */
/* Using CSS Variables */
:root { --gutter: 20px; }
.grid-item {
width: calc((100% - var(--gutter) * 2) / 3);
}
min()
min() picks the SMALLEST value from several options — it acts as a maximum bound.
/* Maximum width 600px */
.container {
width: min(100%, 600px);
/* on mobile: 100% (smaller than 600px) */
/* on desktop: 600px (smaller than 100%) */
}
/* Responsive font with an upper bound */
h1 {
font-size: min(5vw, 24px);
}
/* Padding that does not get excessive */
.card {
padding: min(5vw, 30px);
}
max()
max() picks the LARGEST value from several options — it acts as a minimum bound.
/* Minimum width 300px */
.box {
width: max(50%, 300px);
/* on wide screens: 50% (larger than 300px) */
/* on narrow screens: 300px (larger than 50%) */
}
/* Font never gets too small */
body {
font-size: max(16px, 1.2vw);
}
/* Padding never gets too small */
.section {
padding: max(30px, 5vw);
}
clamp()
clamp(min, preferred, max) is a combination of min() and max() — it constrains a value within a range. The preferred value (middle) is the ideal value that will be used as long as it is within the range.
/* Font: minimum 1rem, ideal 4vw, maximum 3rem */
h1 {
font-size: clamp(1rem, 4vw, 3rem);
}
/* Padding responsive */
.section {
padding: clamp(20px, 5vw, 60px);
}
/* Width with bounds */
.container {
width: clamp(300px, 80%, 1200px);
}
How clamp() works:
- If preferred < min → use min
- If preferred > max → use max
- If min ≤ preferred ≤ max → use preferred
attr()
Uses HTML attribute values as CSS values. Useful for decorative elements or tooltips:
/* Display a data attribute as a pseudo-element */
.tooltip::after {
content: attr(data-tooltip);
}
/* Sequential numbering from an attribute */
.item::before {
content: counter(item) ". ";
counter-increment: item;
}
counter()
Creates automatic numbering:
ol {
counter-reset: list-counter;
}
ol li {
counter-increment: list-counter;
}
ol li::before {
content: counter(list-counter) ". ";
font-weight: bold;
}
Combining Functions
These functions can be combined:
/* clamp + var */
h1 {
font-size: clamp(var(--text-lg), 4vw, var(--text-2xl));
}
/* calc + min */
.container {
width: min(calc(100% - 40px), 1200px);
}
/* clamp + calc + var */
:root { --page-padding: 20px; }
.section {
padding: clamp(var(--page-padding), 5vw, 60px);
}
Everyday Use Cases
1. Fluid Typography Without Media Queries
Before clamp(), you needed media queries to change font size at every breakpoint. Now:
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
h2 { font-size: clamp(1.2rem, 3vw, 2rem); }
p { font-size: clamp(0.9rem, 2vw, 1.1rem); }
One line, zero media queries, and smooth transitions between screen sizes.
2. The Perfect Container
A container that is always centered with responsive padding:
.container {
width: min(90%, 1200px);
margin: 0 auto;
padding: clamp(20px, 4vw, 60px);
}
3. Responsive Grid Gap
A gap that adapts without media queries:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: clamp(15px, 2vw, 30px);
}
4. Dynamic Sidebar Layout
A sidebar + main layout that changes without media queries:
.layout {
display: grid;
grid-template-columns: min(250px, 30%) 1fr;
gap: clamp(15px, 2vw, 30px);
}
5. A Consistent Spacing System
Spacing based on CSS Variables and calc:
:root {
--space: 8px;
}
.space-1 { padding: calc(var(--space) * 1); } /* 8px */
.space-2 { padding: calc(var(--space) * 2); } /* 16px */
.space-3 { padding: calc(var(--space) * 3); } /* 24px */
.space-4 { padding: calc(var(--space) * 4); } /* 32px */
Change --space once, and the entire spacing system changes.
Conclusion
CSS functions eliminate the need for JavaScript for layout calculations:
- calc() — arithmetic operations with mixed units (
100% - 40px,(100% - 60px) / 3). Spaces are required around+and-. - min() — picks the smallest value, acts as a MAXIMUM bound (
min(100%, 600px)). - max() — picks the largest value, acts as a MINIMUM bound (
max(50%, 300px)). - clamp(min, preferred, max) — min+max combined, constrains a value within a range. The preferred value is used while inside the range.
- var() — CSS Variables that can be given fallbacks and changed via JavaScript.
- attr() and counter() — accessing HTML attributes and automatic numbering.
The most powerful technique: clamp() replaces many media queries for responsive typography, spacing, and container widths — resulting in cleaner CSS and better performance.