使用 HSL 的配色方案

此模式显示了如何使用 CSS 自定义属性超越浅色和深色主题。

完整文章 · YouTube 上的视频 · GitHub 上的来源

<header>
 
<h3>Scheme</h3>
 
<form id="theme-switcher">
   
<div>
     
<input checked type="radio" id="auto" name="theme" value="auto">
     
<label for="auto">Auto</label>
   
</div>
   
<div>
     
<input type="radio" id="light" name="theme" value="light">
     
<label for="light">Light</label>
   
</div>
   
<div>
     
<input type="radio" id="dark" name="theme" value="dark">
     
<label for="dark">Dark</label>
   
</div>
   
<div>
     
<input type="radio" id="dim" name="theme" value="dim">
     
<label for="dim">Dim</label>
   
</div>
 
</form>
</header>

<main>
 
<section>
   
<div class="surface-samples">
     
<div class="surface1 rad-shadow">1</div>
     
<div class="surface2 rad-shadow">2</div>
     
<div class="surface3 rad-shadow">3</div>
     
<div class="surface4 rad-shadow">4</div>
   
</div>
 
</section>

 
<section>
   
<div class="text-samples">
     
<h1 class="text1">
       
<span class="swatch brand rad-shadow"></span>
        Brand
     
</h1>
     
<h1 class="text1">
       
<span class="swatch text1 rad-shadow"></span>
        Text Color 1
     
</h1>
     
<h1 class="text2">
       
<span class="swatch text2 rad-shadow"></span>
        Text Color 2
     
</h1>
     
<br>
     
<p class="text1">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
     
<p class="text2">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
   
</div>
 
</section>
</main>

       
* {
 
/* brand foundation */
 
--brand-hue: 200;
 
--brand-saturation: 100%;
 
--brand-lightness: 50%;

 
/* light */
 
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
 
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
 
--text2-light: hsl(var(--brand-hue) 30% 30%);
 
--surface1-light: hsl(var(--brand-hue) 25% 90%);
 
--surface2-light: hsl(var(--brand-hue) 20% 99%);
 
--surface3-light: hsl(var(--brand-hue) 20% 92%);
 
--surface4-light: hsl(var(--brand-hue) 20% 85%);
 
--surface-shadow-light: var(--brand-hue) 10% 20%;
 
--shadow-strength-light: .02;

 
/* dark */
 
--brand-dark: hsl(
    var
(--brand-hue)
    calc
(var(--brand-saturation) / 2)
    calc
(var(--brand-lightness) / 1.5)
 
);
 
--text1-dark: hsl(var(--brand-hue) 15% 85%);
 
--text2-dark: hsl(var(--brand-hue) 5% 65%);
 
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
 
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
 
--surface3-dark: hsl(var(--brand-hue) 5%  20%);
 
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
 
--surface-shadow-dark: var(--brand-hue) 50% 3%;
 
--shadow-strength-dark: .8;

 
/* dim */
 
--brand-dim: hsl(
    var
(--brand-hue)
    calc
(var(--brand-saturation) / 1.25)
    calc
(var(--brand-lightness) / 1.25)
 
);
 
--text1-dim: hsl(var(--brand-hue) 15% 75%);
 
--text2-dim: hsl(var(--brand-hue) 10% 61%);
 
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
 
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
 
--surface3-dim: hsl(var(--brand-hue) 5%  30%);
 
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
 
--surface-shadow-dim: var(--brand-hue) 30% 13%;
 
--shadow-strength-dim: .2;
}

:root {
 
color-scheme: light;

 
/* set defaults */
 
--brand: var(--brand-light);
 
--text1: var(--text1-light);
 
--text2: var(--text2-light);
 
--surface1: var(--surface1-light);
 
--surface2: var(--surface2-light);
 
--surface3: var(--surface3-light);
 
--surface4: var(--surface4-light);
 
--surface-shadow: var(--surface-shadow-light);
 
--shadow-strength: var(--shadow-strength-light);
}

@media (prefers-color-scheme: dark) {
 
:root {
   
color-scheme: dark;

   
--brand: var(--brand-dark);
   
--text1: var(--text1-dark);
   
--text2: var(--text2-dark);
   
--surface1: var(--surface1-dark);
   
--surface2: var(--surface2-dark);
   
--surface3: var(--surface3-dark);
   
--surface4: var(--surface4-dark);
   
--surface-shadow: var(--surface-shadow-dark);
   
--shadow-strength: var(--shadow-strength-dark);
 
}
}

[color-scheme="light"] {
 
color-scheme: light;

 
--brand: var(--brand-light);
 
--text1: var(--text1-light);
 
--text2: var(--text2-light);
 
--surface1: var(--surface1-light);
 
--surface2: var(--surface2-light);
 
--surface3: var(--surface3-light);
 
--surface4: var(--surface4-light);
 
--surface-shadow: var(--surface-shadow-light);
 
--shadow-strength: var(--shadow-strength-light);
}

[color-scheme="dark"] {
 
color-scheme: dark;

 
--brand: var(--brand-dark);
 
--text1: var(--text1-dark);
 
--text2: var(--text2-dark);
 
--surface1: var(--surface1-dark);
 
--surface2: var(--surface2-dark);
 
--surface3: var(--surface3-dark);
 
--surface4: var(--surface4-dark);
 
--surface-shadow: var(--surface-shadow-dark);
 
--shadow-strength: var(--shadow-strength-dark);
}

[color-scheme="dim"] {
 
color-scheme: dark;

 
--brand: var(--brand-dim);
 
--text1: var(--text1-dim);
 
--text2: var(--text2-dim);
 
--surface1: var(--surface1-dim);
 
--surface2: var(--surface2-dim);
 
--surface3: var(--surface3-dim);
 
--surface4: var(--surface4-dim);
 
--surface-shadow: var(--surface-shadow-dim);
 
--shadow-strength: var(--shadow-strength-dim);
}

/* READY TO USE! */
.brand {
 
color: var(--brand);
 
background-color: var(--brand);
}

.surface1 {
 
background-color: var(--surface1);
 
color: var(--text2);
}

.surface2 {
 
background-color: var(--surface2);
 
color: var(--text2);
}

.surface3 {
 
background-color: var(--surface3);
 
color: var(--text1);
}

.surface4 {
 
background-color: var(--surface4);
 
color: var(--text1);
}

.text1 {
 
color: var(--text1);
}

p
.text1 {
 
font-weight: 200;
}

.text2 {
 
color: var(--text2);
}
       

       
const switcher = document.querySelector('#theme-switcher')
const doc = document.firstElementChild

switcher
.addEventListener('input', e =>
  setTheme
(e.target.value))

const setTheme = theme =>
  doc
.setAttribute('color-scheme', theme)