obsidian/wiki/concepts/css-clamp-negative-values.md
2026-05-14 21:09:52 +01:00

1.8 KiB
Raw Blame History

name description type
css-clamp-negative-values CSS clamp() with negative values has reversed MIN/MAX semantics — the most-negative value is the constraint floor, not the ceiling concept

CSS clamp() with Negative Values — Reversed Semantics

The Gotcha

clamp(MIN, VALUE, MAX) always returns a value between MIN and MAX. With negative values, the "minimum" must be the most-negative number — which visually looks like the largest negative magnitude.

/* WRONG — clamp semantics violated: MIN > MAX */
margin-top: clamp(-4px, -0.5vw, -1px);
/* ^ result is always -4px (MIN wins), intended range never applies */

/* CORRECT */
margin-top: clamp(-4px, -0.5vw, -1px);
/* MIN=-4px (most negative = floor), MAX=-1px (least negative = ceiling) */

Wait — that's the same example. The key rule:

For negative ranges: MIN must be the most negative, MAX must be the least negative.

clamp(-40px, -2.78vw, -10px)  ✓  (-40 ≤ result ≤ -10)
clamp(-10px, -2.78vw, -40px)  ✗  (MIN > MAX, clamp always returns -10px)

vw → px Conversion

To hit an exact pixel value at a reference viewport width:

vw% = target_px / reference_width_px × 100

Example: -20px at 1440px wide
vw = -20 / 1440 × 100 = -1.389vw

Practical Pattern

Fluid negative margin/gap that scales between viewports:

.element {
  /* -40px on narrow, scales to -10px at wide viewports */
  margin-top: clamp(-40px, -2.78vw, -10px);
}

Why It's a Silent Bug

  • The browser doesn't warn when MIN > MAX in a negative clamp.
  • The static fallback value (MIN) is used constantly — layout looks "fine" but never responds to viewport size.
  • Detected only when resizing and noticing the value never changes.

Source: daily/2026-05-13.md | 2026-05-13