Modern CSS math: clamp, type scale, and specificity

|
web css design

Modern CSS expects you to think in formulas. Fluid typography uses clamp() to interpolate between breakpoints. Type scales use a multiplier to derive consistent heading sizes. Specificity is a three-digit score that determines which rule wins. Viewport units, aspect ratios, and color contrast all reduce to math you can do in your head once you know the formula. This guide covers the five most useful CSS calculations with examples you can paste directly into a stylesheet.

CSS clamp() for fluid values

clamp(MIN, PREFERRED, MAX) lets a value scale smoothly between two limits as the viewport changes. It is the cleanest replacement for media query stacks that adjust font size or spacing at every breakpoint.

font-size: clamp(1rem, 0.5rem + 2vw, 2rem);

This font-size starts at 1rem on small screens, scales upward as the viewport widens, and caps at 2rem on large screens. The middle value (0.5rem + 2vw) is the formula that determines the actual size at any viewport width.

The math behind the middle value: at viewport width W, the size becomes 0.5rem + (W × 2 / 100). At 320px (mobile): 0.5 + 6.4 = 6.9px (clamped to 1rem floor). At 1280px: 0.5 + 25.6 = 26.1px (close to the 2rem cap of 32px).

To derive the clamp values from two breakpoint sizes:

\[\text{slope} = \frac{\text{Max Size} - \text{Min Size}}{\text{Max Viewport} - \text{Min Viewport}}\] \[\text{intercept} = \text{Min Size} - \text{slope} \times \text{Min Viewport}\]

For 1rem at 320px scaling to 2rem at 1280px (sizes in px: 16 and 32):

  • Slope: (32 - 16) / (1280 - 320) = 16 / 960 ≈ 0.0167
  • Intercept: 16 - 0.0167 × 320 = 10.67px

Final formula in CSS units: clamp(1rem, 10.67px + 1.67vw, 2rem). The CSS clamp calculator does this conversion automatically.

Type scale ratios

A type scale is a sequence of sizes derived by multiplying or dividing by a fixed ratio. Picking a single ratio (e.g., 1.25) and applying it consistently produces visual harmony across all heading levels.

\[\text{Size}_n = \text{Base Size} \times \text{Ratio}^n\]

Common ratios:

Name Ratio Use case
Minor second 1.067 Subtle, body-heavy designs
Major second 1.125 Subtle, slight contrast
Minor third 1.2 Default scale
Major third 1.25 Standard editorial
Perfect fourth 1.333 Bold contrast
Augmented fourth 1.414 High contrast (Tailwind default)
Perfect fifth 1.5 Marketing pages
Golden ratio 1.618 Display-heavy designs

For a 1rem (16px) base with a 1.25 ratio:

Step Multiplier Size (rem) Size (px)
-1 / 1.25 0.8 12.8
0 (base) × 1 1.0 16
1 × 1.25 1.25 20
2 × 1.25² 1.563 25
3 × 1.25³ 1.953 31.25
4 × 1.25⁴ 2.441 39
5 × 1.25⁵ 3.052 48.8

Map these to HTML elements: h6 = step 0, h5 = step 1, h4 = step 2, etc. The type scale calculator generates the full scale at any base size and ratio.

CSS specificity

When two CSS rules target the same element, specificity decides which one wins. Specificity is a three-digit score: (IDs, classes/attributes/pseudo-classes, elements/pseudo-elements). The selector with the higher score wins; ties go to the rule defined later.

Quick scoring:

Selector type Score
Element (div, p) 0,0,1
Pseudo-element (::before) 0,0,1
Class (.btn) 0,1,0
Attribute ([type="text"]) 0,1,0
Pseudo-class (:hover) 0,1,0
ID (#header) 1,0,0
Inline style 1,0,0,0
!important overrides everything

Examples:

Selector Specificity
p 0,0,1
.btn 0,1,0
#header 1,0,0
nav a:hover 0,1,2
.card .title 0,2,0
#sidebar p.note 1,1,1
body #main .article p 1,1,2

Important rules:

  • Specificity is compared digit by digit. (1,0,0) beats (0,9,9). One ID outweighs nine classes.
  • The universal selector (*) and combinators (>, +, ~) add zero specificity.
  • :not(), :is(), :where() have special rules. :where() always contributes zero. :not() and :is() use the highest-specificity argument inside.

The CSS specificity calculator parses any selector string and shows the breakdown.

Viewport units (vw, vh, vmin, vmax)

Viewport units measure relative to the browser window:

  • 1vw = 1% of viewport width
  • 1vh = 1% of viewport height
  • 1vmin = 1% of the smaller dimension
  • 1vmax = 1% of the larger dimension

For a 1920 × 1080 desktop viewport:

Unit Pixel value
1vw 19.2px
1vh 10.8px
1vmin 10.8px
1vmax 19.2px

For a 375 × 812 mobile viewport:

Unit Pixel value
1vw 3.75px
1vh 8.12px
1vmin 3.75px
1vmax 8.12px

Common patterns:

/* Full-screen hero section */
.hero { min-height: 100vh; }

/* Fluid heading with viewport units */
h1 { font-size: clamp(2rem, 5vw, 4rem); }

/* Responsive padding */
section { padding: 5vmin; }

Modern CSS also includes dvh (dynamic viewport height) which accounts for mobile address bar collapse, and lvh/svh for large/small viewport variants. These solve the long-standing “100vh is too tall on mobile” problem. Use the viewport unit calculator to convert px to vw at any reference width.

Aspect ratio

Aspect ratio is width divided by height, expressed as W:H. The classic 16:9 means a width of 16 units for every 9 units of height.

\[\text{Aspect Ratio} = \frac{\text{Width}}{\text{Height}}\]

To find any missing dimension when the ratio is fixed:

\[\text{Height} = \text{Width} \times \frac{H}{W}\]

For a 16:9 hero image at 1200px wide: height = 1200 × 9/16 = 675px.

Common ratios:

Ratio Decimal Use case
1:1 1.000 Square (Instagram, profile photos)
4:3 1.333 Old TV, iPad
3:2 1.500 DSLR photos
16:10 1.600 Older laptops
16:9 1.778 HD video, modern displays
21:9 2.333 Ultrawide cinema

The CSS aspect-ratio property reserves space without explicit dimensions:

.video { aspect-ratio: 16 / 9; width: 100%; }
.thumbnail { aspect-ratio: 1; width: 200px; }

This prevents layout shift when the actual content (image, video) loads later. The aspect ratio calculator handles dimension conversion in any direction.

Color contrast (WCAG)

Color contrast is the ratio between the relative luminance of foreground and background:

\[\text{Contrast Ratio} = \frac{L_1 + 0.05}{L_2 + 0.05}\]

Where L₁ is the lighter color’s luminance and L₂ is the darker color’s. The result ranges from 1:1 (no contrast) to 21:1 (black on white).

WCAG accessibility thresholds:

Level Normal text Large text (18pt+ or 14pt+ bold)
AA (minimum) 4.5:1 3:1
AAA (enhanced) 7:1 4.5:1

The luminance formula is more involved (it requires gamma correction on each RGB channel), but the ratio comparison is straightforward once you have the luminance values. The color contrast checker handles both calculations.

Putting it together

A reusable CSS pattern for a card heading using all of the above:

.card-title {
  /* Type scale step 2 with 1.25 ratio from 1rem base */
  font-size: clamp(1.25rem, 1rem + 1vw, 1.563rem);

  /* Maintain readable line length */
  max-width: 60ch;

  /* High contrast for AA */
  color: #1a1a1a;
  /* on a white background = 18.4:1, exceeds AAA */
}

.card-image {
  aspect-ratio: 16 / 9;
  width: 100%;
}

Each line ties back to a specific calculation. The CSS specification gives you the math; the calculators do the arithmetic.