CSS Mathematical Functions
Perform calculations and create dynamic values in CSS. These functions enable responsive designs and complex layouts without JavaScript.
💻 calc() Function
/* Basic calculations */
.element {
width: calc(100% - 50px);
height: calc(100vh - 80px);
margin: calc(10px + 5px);
}
/* Operators: + - * / */
.box {
width: calc(50% - 20px); /* Subtraction */
padding: calc(10px + 5px); /* Addition */
font-size: calc(16px * 1.5); /* Multiplication */
line-height: calc(24px / 16px); /* Division */
}
/* Mix units */
.mixed {
width: calc(100% - 100px);
padding: calc(2em + 10px);
margin: calc(50% - 2rem);
}
/* Nested calc */
.nested {
width: calc(100% - calc(20px * 2));
}
/* With CSS variables */
:root {
--spacing: 20px;
--multiplier: 2;
}
.dynamic {
padding: calc(var(--spacing) * var(--multiplier));
width: calc(100% - var(--spacing) * 2);
}
/* Examples */
/* Full width minus sidebar */
.content {
width: calc(100% - 250px);
}
/* Viewport height minus header and footer */
.main {
min-height: calc(100vh - 60px - 80px);
}
/* Center with calc */
.centered {
position: absolute;
left: calc(50% - 100px); /* 100px = half of element width */
top: calc(50% - 50px);
}
📏 min(), max(), clamp()
min() - Smallest Value
/* Use smallest value */
.element {
width: min(100%, 600px);
/* Width is 100% OR 600px, whichever is smaller */
}
/* Multiple values */
.box {
width: min(100%, 600px, 50vw);
/* Smallest of: 100%, 600px, or 50vw */
}
/* Responsive padding */
.container {
padding: min(5%, 50px);
/* 5% on large screens, max 50px */
}
/* Font size limit */
.text {
font-size: min(5vw, 24px);
/* Scales with viewport but never exceeds 24px */
}
max() - Largest Value
/* Use largest value */
.element {
width: max(200px, 50%);
/* Width is 200px OR 50%, whichever is larger */
}
/* Minimum width guarantee */
.card {
width: max(300px, 25%);
/* Never smaller than 300px */
}
/* Responsive minimum height */
.section {
min-height: max(400px, 50vh);
}
/* Minimum font size */
.text {
font-size: max(16px, 1vw);
/* Never smaller than 16px for readability */
}
clamp() - Bounded Value
/* clamp(minimum, preferred, maximum) */
.element {
width: clamp(200px, 50%, 800px);
/* min: 200px, preferred: 50%, max: 800px */
}
/* Fluid typography */
.heading {
font-size: clamp(1.5rem, 5vw, 3rem);
/* min: 1.5rem, scales with viewport, max: 3rem */
}
body {
font-size: clamp(1rem, 2.5vw, 1.25rem);
/* Fluid text size between 16px and 20px */
}
/* Responsive padding */
.container {
padding: clamp(1rem, 5vw, 3rem);
}
/* Responsive spacing */
.section {
margin-bottom: clamp(2rem, 8vw, 6rem);
}
/* Line length control */
.text-content {
max-width: clamp(45ch, 80%, 75ch);
/* Optimal line length: 45-75 characters */
}
/* Gap in grid */
.grid {
gap: clamp(1rem, 3vw, 2rem);
}
🎯 Comparison Functions
/* min() for responsive design */
.responsive-width {
width: min(90%, 1200px);
/* 90% of viewport but never more than 1200px */
}
/* max() for minimum sizes */
.card {
width: max(300px, 33.333%);
/* At least 300px wide, even on small screens */
}
/* clamp() for fluid scaling */
h1 {
font-size: clamp(2rem, 5vw + 1rem, 4rem);
/* Scales smoothly between 2rem and 4rem */
}
/* Combine with calc() */
.complex {
width: clamp(
200px,
calc(50% - 20px),
600px
);
}
/* Container with constraints */
.container {
width: min(100% - 40px, 1200px);
margin: 0 auto;
}
🔢 Mathematical Functions
Trigonometric Functions
/* sin() - Sine */
.element {
transform: rotate(sin(45deg));
}
/* cos() - Cosine */
.element {
transform: translateX(cos(60deg) * 100px);
}
/* tan() - Tangent */
.element {
height: calc(100px * tan(45deg));
}
/* asin(), acos(), atan() - Inverse functions */
.angle {
transform: rotate(asin(0.5));
transform: rotate(acos(0.5));
transform: rotate(atan(1));
}
/* atan2() - Two-argument arctangent */
.element {
transform: rotate(atan2(1, 1)); /* 45deg */
}
Exponential Functions
/* pow() - Power */
.element {
width: calc(pow(2, 3) * 10px); /* 2^3 * 10px = 80px */
}
/* sqrt() - Square root */
.element {
width: calc(sqrt(16) * 20px); /* 4 * 20px = 80px */
}
/* hypot() - Hypotenuse */
.element {
width: calc(hypot(3, 4) * 10px); /* 5 * 10px = 50px */
}
/* log() - Logarithm */
.element {
opacity: calc(log(10));
}
/* exp() - Exponential */
.element {
transform: scale(exp(1)); /* e ≈ 2.718 */
}
Sign-Related Functions
/* abs() - Absolute value */
.element {
margin: calc(abs(-20px)); /* 20px */
}
/* sign() - Sign of number */
.element {
--value: -5;
transform: translateX(calc(sign(var(--value)) * 100px));
/* -1 * 100px = -100px */
}
/* Round functions */
/* round() - Round to nearest */
.element {
width: calc(round(15.7px)); /* 16px */
}
/* mod() - Modulo */
.element {
width: calc(mod(17px, 5px)); /* 2px */
}
/* rem() - Remainder */
.element {
width: calc(rem(17px, 5px)); /* 2px */
}
🎨 Color Functions
/* rgb() and rgba() */
.color-rgb {
background: rgb(255, 0, 0);
background: rgba(255, 0, 0, 0.5);
}
/* hsl() and hsla() */
.color-hsl {
background: hsl(240, 100%, 50%); /* Blue */
background: hsla(240, 100%, 50%, 0.5);
}
/* hwb() - Hue, Whiteness, Blackness */
.color-hwb {
background: hwb(240 0% 0%); /* Pure blue */
background: hwb(240 20% 0%); /* Lighter blue */
}
/* lab() - Lab color space */
.color-lab {
background: lab(50% 0 0); /* Mid gray */
}
/* lch() - Lightness, Chroma, Hue */
.color-lch {
background: lch(50% 50 240);
}
/* color-mix() - Mix two colors */
.mixed {
background: color-mix(in srgb, red 50%, blue);
/* 50% red, 50% blue */
}
/* Relative colors (modern) */
.relative {
--base-color: blue;
background: rgb(from var(--base-color) r g b / 50%);
}
🎯 Practical Examples
/* Responsive container */
.container {
width: min(100% - 40px, 1200px);
margin: 0 auto;
padding: clamp(1rem, 5vw, 3rem);
}
/* Fluid typography system */
:root {
--font-size-sm: clamp(0.875rem, 1vw, 1rem);
--font-size-base: clamp(1rem, 2vw, 1.125rem);
--font-size-lg: clamp(1.125rem, 3vw, 1.5rem);
--font-size-xl: clamp(1.5rem, 4vw, 2rem);
--font-size-2xl: clamp(2rem, 5vw, 3rem);
--font-size-3xl: clamp(2.5rem, 6vw, 4rem);
}
h1 { font-size: var(--font-size-3xl); }
h2 { font-size: var(--font-size-2xl); }
h3 { font-size: var(--font-size-xl); }
/* Responsive grid with minimum item width */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(1rem, 3vw, 2rem);
}
/* Full-height layout with fixed header */
.layout {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.header {
height: 60px;
}
.main {
min-height: calc(100vh - 60px - 80px);
}
.footer {
height: 80px;
}
/* Sidebar layout */
.page {
display: grid;
grid-template-columns: minmax(200px, 250px) 1fr;
gap: clamp(1rem, 3vw, 2rem);
}
@media (max-width: 768px) {
.page {
grid-template-columns: 1fr;
}
}
/* Card grid with constraints */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(clamp(250px, 30%, 350px), 1fr));
gap: clamp(1rem, 2vw, 2rem);
}
/* Responsive spacing scale */
:root {
--space-xs: clamp(0.25rem, 1vw, 0.5rem);
--space-sm: clamp(0.5rem, 2vw, 1rem);
--space-md: clamp(1rem, 3vw, 1.5rem);
--space-lg: clamp(1.5rem, 4vw, 2rem);
--space-xl: clamp(2rem, 5vw, 3rem);
--space-2xl: clamp(3rem, 6vw, 4rem);
}
.section {
padding: var(--space-xl) var(--space-md);
margin-bottom: var(--space-2xl);
}
/* Aspect ratio with calc */
.aspect-16-9 {
height: 0;
padding-bottom: calc(9 / 16 * 100%);
position: relative;
}
.aspect-16-9 > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Dynamic columns based on container width */
.dynamic-columns {
column-count: max(1, min(4, calc((100% - 300px) / 300px)));
column-gap: clamp(1rem, 3vw, 2rem);
}
/* Button with responsive padding */
.button {
padding: clamp(0.5rem, 2vw, 1rem) clamp(1rem, 4vw, 2rem);
font-size: clamp(0.875rem, 2vw, 1rem);
}
/* Responsive border radius */
.card {
border-radius: clamp(8px, 1vw, 16px);
}
/* Optimal line length */
.text-content {
max-width: min(65ch, 100%);
margin: 0 auto;
}
/* Navigation with flexible spacing */
nav {
display: flex;
gap: clamp(1rem, 3vw, 2rem);
padding: clamp(0.5rem, 2vw, 1rem);
}
/* Hero section height */
.hero {
min-height: clamp(400px, 60vh, 800px);
display: flex;
align-items: center;
justify-content: center;
}
/* Responsive icon size */
.icon {
width: clamp(20px, 5vw, 40px);
height: clamp(20px, 5vw, 40px);
}
/* Form field spacing */
.form-field {
margin-bottom: clamp(1rem, 3vw, 1.5rem);
}
.form-field input {
padding: clamp(0.5rem, 2vw, 0.75rem);
font-size: clamp(0.875rem, 2vw, 1rem);
}
/* Modal width constraints */
.modal {
width: clamp(300px, 90vw, 600px);
padding: clamp(1rem, 4vw, 2rem);
}
/* Gallery item size */
.gallery-item {
width: clamp(150px, calc(33.333% - 20px), 300px);
height: clamp(150px, 25vw, 300px);
}
/* Footer with minimum height */
.footer {
min-height: max(100px, 10vh);
padding: clamp(1rem, 3vw, 2rem);
}
💡 Best Practices
/* 1. Use clamp() for fluid typography */
/* Good - scales smoothly */
h1 {
font-size: clamp(2rem, 5vw, 4rem);
}
/* Bad - abrupt changes */
h1 {
font-size: 2rem;
}
@media (min-width: 768px) {
h1 { font-size: 4rem; }
}
/* 2. Prefer min() for responsive containers */
.container {
width: min(100% - 2rem, 1200px);
margin: 0 auto;
}
/* 3. Use max() for minimum sizes */
.button {
min-width: max(120px, 20%);
}
/* 4. Always provide fallbacks for older browsers */
.element {
width: 50%; /* Fallback */
width: clamp(200px, 50%, 800px);
}
/* 5. Use calc() with CSS variables */
:root {
--header-height: 60px;
--footer-height: 80px;
}
.content {
min-height: calc(100vh - var(--header-height) - var(--footer-height));
}
/* 6. Be mindful of performance */
/* Expensive (recalculates on every change) */
.expensive {
width: calc(100vw - 100%);
}
/* Better (static calculation) */
.better {
width: calc(100% - 100px);
}
/* 7. Use appropriate units */
/* Good - mixing compatible units */
.element {
width: calc(100% - 50px);
}
/* Bad - incompatible for some calculations */
.element {
width: calc(100% * 50px); /* Doesn't work */
}
/* 8. Add spacing in calc() */
/* Good - readable */
.element {
width: calc(100% - 50px);
}
/* Bad - hard to read */
.element {
width: calc(100%-50px);
}
🎯 Key Takeaways
- calc(): Perform calculations mixing units (+, -, *, /)
- min(): Choose smallest value (responsive maximum)
- max(): Choose largest value (responsive minimum)
- clamp(): Bounded value (min, preferred, max)
- Fluid typography: Use clamp() for responsive text
- Unit mixing: calc() can mix px, %, rem, vw, etc.
- Variables: Combine with CSS variables for dynamic values
- Browser support: Modern browsers support all these functions