Auto-Detection

How Nightfall determines whether your site is light or dark — no configuration required.

How It Works

When you run Nightfall without a --direction flag, it automatically detects whether your UI is in light mode or dark mode. This detection happens in OKLCH color space for perceptual accuracy.

  1. Sample the background — Nightfall reads the computed background-color of the root element and major surface containers.
  2. Compute weighted average lightness — Each sampled color is converted to OKLCH. The lightness (L) values are averaged, weighted by the element's visible area in the viewport.
  3. Classify the theme — The weighted average L value determines the direction.

Detection Thresholds

The decision boundaries are based on OKLCH lightness (L ranges from 0 to 1):

# Detection thresholds
L > 0.6  →  Light mode detected  →  generates dark theme
L < 0.4  →  Dark mode detected   →  generates light theme
0.4 ≤ L ≤ 0.6  →  Ambiguous  →  falls back to --direction flag

The ambiguous zone (0.4 to 0.6) covers mid-tone UIs where the intent is unclear. In these cases, Nightfall requires you to specify the direction explicitly.

Weighted Sampling

Not all elements contribute equally. A full-screen hero background matters more than a tiny badge. Nightfall weights each sample by its pixel area relative to the viewport:

detection-algorithm.js
// Simplified detection logic
function detectDirection(elements) {
  let totalWeight = 0;
  let weightedL = 0;

  for (const el of elements) {
    const rect = el.getBoundingClientRect();
    const area = rect.width * rect.height;
    const bg = getComputedStyle(el).backgroundColor;
    const oklch = toOKLCH(bg);

    weightedL += oklch.l * area;
    totalWeight += area;
  }

  const avgL = weightedL / totalWeight;

  if (avgL > 0.6) return "light-to-dark";
  if (avgL < 0.4) return "dark-to-light";
  return "ambiguous";
}

Overriding Auto-Detection

If auto-detection picks the wrong direction (rare, but possible with unusual color schemes), override it with the --direction flag:

# Force light-to-dark even if detection says otherwise
npx nightfall-css scan --url http://localhost:3000 --direction light-to-dark

# Force dark-to-light
npx nightfall-css scan --url http://localhost:3000 --direction dark-to-light

Debugging Detection

Use the --verbose flag to see exactly what Nightfall detected:

npx nightfall-css scan --url http://localhost:3000 --verbose

# Output:
# [detect] Sampled 14 background surfaces
# [detect] Weighted avg lightness: L=0.94
# [detect] Classification: LIGHT (L > 0.6)
# [detect] Direction: light-to-dark