Skillversitas

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.