color-mix()

Mixes two colors directly in CSS — tint/shade variants without Sass's `mix()` or a JS color library.

Also known as: CSS color mixing
···
html
<div class="wrap">
  <div class="badge" id="badge"><svg viewBox="0 0 10 10"><path id="bpath" d="M1.5 5.2l2.6 2.6L8.5 2.4" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg><span id="btext">확인 중</span></div>
  <div class="row" id="row">
    <div class="sw" style="--p:90%"></div><div class="sw" style="--p:70%"></div><div class="sw" style="--p:50%"></div>
    <div class="sw" style="--p:30%"></div><div class="sw" style="--p:10%"></div>
  </div>
</div>
css
.wrap{position:relative;width:min(320px,92%)}
.row{display:flex;gap:8px}
.sw{flex:1;height:52px;border-radius:8px;background:color-mix(in oklch, var(--accent) var(--p), white)}
.row.fallback .sw:nth-child(1){background:#c7c6fb}.row.fallback .sw:nth-child(2){background:#9d9cf9}
.row.fallback .sw:nth-child(3){background:#7373f8}.row.fallback .sw:nth-child(4){background:#4a49e0}.row.fallback .sw:nth-child(5){background:#2f2ea8}
.badge{position:absolute;top:-30px;right:0;display:flex;align-items:center;gap:5px;padding:4px 9px;border-radius:999px;font-size:10px;font-weight:700;background:var(--bg);border:1px solid var(--line);color:var(--accent-3)}
.badge.no{color:var(--accent-2)}
.badge svg{width:9px;height:9px}
js
const ok = CSS.supports('color', 'color-mix(in oklch, red 50%, blue)');
const b=document.getElementById('badge'),p=document.getElementById('bpath'),t=document.getElementById('btext');
b.classList.toggle('no', !ok);
p.setAttribute('d', ok ? 'M1.5 5.2l2.6 2.6L8.5 2.4' : 'M2 2l6 6M8 2l-6 6');
t.textContent = ok ? 'color-mix() 지원됨' : '미지원 · 정적 팔레트 폴백';
if (!ok) document.getElementById('row').classList.add('fallback');

Deriving a lighter background, a darker text color, or a translucent border from one brand color used to belong to preprocessors (Sass's `mix()`, `lighten()`) or a JS color math library — plain CSS had no "blend this color with that one at 70/30" operation.

`color-mix(in oklch, var(--accent) 70%, white)` names a color space and a ratio and lets the browser do the blending. Picking the interpolation space matters — `in oklch` or `in oklab` shift perceived lightness evenly, avoiding the muddy midtones sRGB mixing produces. Paired with custom properties, one design token can derive every hover/disabled tone.

Check caniuse/MDN baseline for support. Without it, precomputed static color values (from a preprocessor or JS) plugged straight into the custom property are the fallback.

When to use

Deriving several tonal variants — hover, disabled, tinted background — from a single brand color.