<form class="pick-a-color">
<label for="base-color">Pick a Base Color: </label>
<input type="color" id="base-color" value="#FF7F00">
</form>
<main class="palette">
<details class="key" closed>
<summary>Terms:</summary>
<ul>
<li><b>Tints:</b> Lightens the primary color by adding a percentage of white.</li>
<li><b>Shades:</b> Darkens the primary color by adding a percentage of black.</li>
<li><b>Transparency:</b> Adjusts the primary color’s opacity by applying a percentage of transparency.</li>
<li><b>Neutral:</b> Blends the primary color into a black-to-neutral palette by adding a percentage of it.</li>
</ul>
</details>
<section class="palette-group">
<div class="palette-group__header">
<h2>Tints</h2>
<!-- <p>adds a percentage of thie white colour to the primary colour</p> -->
</div>
<div class="color-block" data-color="--color-primary--tint-10">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>10%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-20">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>20%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-30">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>30%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-40">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>40%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-50">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>50%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-60">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>60%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-70">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>70%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-80">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>80%</p>
</div>
<div class="color-block" data-color="--color-primary--tint-90">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>90%</p>
</div>
</section>
<section class="palette-group">
<div class="palette-group__header">
<h2>Shades</h2>
</div>
<div class="color-block" data-color="--color-primary--shade-10">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>10%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-20">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>20%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-30">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>30%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-40">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>40%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-50">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>50%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-60">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>60%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-70">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>70%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-80">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>80%</p>
</div>
<div class="color-block" data-color="--color-primary--shade-90">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>90%</p>
</div>
</section>
<section class="palette-group palette-group--transparency">
<div class="palette-group__header">
<h2>Transparency</h2>
</div>
<div class="color-block" data-color="--color-primary--transparency-10">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>10%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-20">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>20%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-30">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>30%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-40">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>40%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-50">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>50%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-60">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>60%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-70">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>70%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-80">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>80%</p>
</div>
<div class="color-block" data-color="--color-primary--transparency-90">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>90%</p>
</div>
</section>
<section class="palette-group palette-group--neutral">
<div class="palette-group__header">
<h2>Neutral</h2>
<form action="">
<div class="form-item">
<label for="neutral-percentage" class="visually-hidden">Adjust Neutral Blend:</label>
<input type="range" id="neutral-percentage" min="0" max="10" value="3" step="1" aria-label="Adjust neutral percentage" />
<span id="neutral-value">3%</span>
</div>
</form>
</div>
<div class="color-block" data-color="--color-neutral-10">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>10% </p>
</div>
<div class="color-block" data-color="--color-neutral-20">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>20% </p>
</div>
<div class="color-block" data-color="--color-neutral-30">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>30% </p>
</div>
<div class="color-block" data-color="--color-neutral-40">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>40% </p>
</div>
<div class="color-block" data-color="--color-neutral-50">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>50% </p>
</div>
<div class="color-block" data-color="--color-neutral-60">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>60% </p>
</div>
<div class="color-block" data-color="--color-neutral-70">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>70% </p>
</div>
<div class="color-block" data-color="--color-neutral-80">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>80% </p>
</div>
<div class="color-block" data-color="--color-neutral-90">
<div class="color-swatch"></div>
<p class="percentage"><span>with </span>90% </p>
</div>
</section>
<pre>
<button class="copy-btn" aria-label="Copy code to clipboard">Copy</button>
<code class="language-css">:root {
/* Base Colors */
--color-primary: #bada55;
--color-white: #ffffff;
--color-black: #000000;
/* Tints */
--color-primary--tint-10: color-mix(in srgb, var(--color-primary), var(--color-white) 10%);
--color-primary--tint-20: color-mix(in srgb, var(--color-primary), var(--color-white) 20%);
--color-primary--tint-30: color-mix(in srgb, var(--color-primary), var(--color-white) 30%);
--color-primary--tint-40: color-mix(in srgb, var(--color-primary), var(--color-white) 40%);
--color-primary--tint-50: color-mix(in srgb, var(--color-primary), var(--color-white) 50%);
--color-primary--tint-60: color-mix(in srgb, var(--color-primary), var(--color-white) 60%);
--color-primary--tint-70: color-mix(in srgb, var(--color-primary), var(--color-white) 70%);
--color-primary--tint-80: color-mix(in srgb, var(--color-primary), var(--color-white) 80%);
--color-primary--tint-90: color-mix(in srgb, var(--color-primary), var(--color-white) 90%);
/* Shades */
--color-primary--shade-10: color-mix(in srgb, var(--color-primary), var(--color-black) 10%);
--color-primary--shade-20: color-mix(in srgb, var(--color-primary), var(--color-black) 20%);
--color-primary--shade-30: color-mix(in srgb, var(--color-primary), var(--color-black) 30%);
--color-primary--shade-40: color-mix(in srgb, var(--color-primary), var(--color-black) 40%);
--color-primary--shade-50: color-mix(in srgb, var(--color-primary), var(--color-black) 50%);
--color-primary--shade-60: color-mix(in srgb, var(--color-primary), var(--color-black) 60%);
--color-primary--shade-70: color-mix(in srgb, var(--color-primary), var(--color-black) 70%);
--color-primary--shade-80: color-mix(in srgb, var(--color-primary), var(--color-black) 80%);
--color-primary--shade-90: color-mix(in srgb, var(--color-primary), var(--color-black) 90%);
/* Opacity */
--color-primary--transparency-10: color-mix(in srgb, var(--color-primary), transparent 10%);
--color-primary--transparency-20: color-mix(in srgb, var(--color-primary), transparent 20%);
--color-primary--transparency-30: color-mix(in srgb, var(--color-primary), transparent 30%);
--color-primary--transparency-40: color-mix(in srgb, var(--color-primary), transparent 40%);
--color-primary--transparency-50: color-mix(in srgb, var(--color-primary), transparent 50%);
--color-primary--transparency-60: color-mix(in srgb, var(--color-primary), transparent 60%);
--color-primary--transparency-70: color-mix(in srgb, var(--color-primary), transparent 70%);
--color-primary--transparency-80: color-mix(in srgb, var(--color-primary), transparent 80%);
--color-primary--transparency-90: color-mix(in srgb, var(--color-primary), transparent 90%);
/* Neutral */
--color-neutral-10: color-mix(in srgb, var(--color-black) 10%, var(--color-primary) 3%);
--color-neutral-20: color-mix(in srgb, var(--color-black) 20%, var(--color-primary) 3%);
--color-neutral-30: color-mix(in srgb, var(--color-black) 30%, var(--color-primary) 3%);
--color-neutral-40: color-mix(in srgb, var(--color-black) 40%, var(--color-primary) 3%);
--color-neutral-50: color-mix(in srgb, var(--color-black) 50%, var(--color-primary) 3%);
--color-neutral-60: color-mix(in srgb, var(--color-black) 60%, var(--color-primary) 3%);
--color-neutral-70: color-mix(in srgb, var(--color-black) 70%, var(--color-primary) 3%);
--color-neutral-80: color-mix(in srgb, var(--color-black) 80%, var(--color-primary) 3%);
--color-neutral-90: color-mix(in srgb, var(--color-black) 90%, var(--color-primary) 3%);
}</code>
</pre>
</main>
<div class="original-post">
<p>This CodePen has an associated article on <a href="https://www.alwaystwisted.com/articles/quick-and-dirty-colour-palettes-using-color-mix">Quick and Dirty Colour Palettes using color-mix()</a></p>
<p>🙏🖤</p>
</div>
*,
*::before,
*::after {
box-sizing: border-box;
}
:root {
/* Base Colors */
--color-primary: #ff751f;
--color-white: #ffffff;
--color-black: #000000;
--neutral-percentage: 3%;
/* Tints */
--color-primary--tint-10: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 10%
);
--color-primary--tint-20: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 20%
);
--color-primary--tint-30: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 30%
);
--color-primary--tint-40: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 40%
);
--color-primary--tint-50: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 50%
);
--color-primary--tint-60: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 60%
);
--color-primary--tint-70: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 70%
);
--color-primary--tint-80: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 80%
);
--color-primary--tint-90: color-mix(
in srgb,
var(--color-primary),
var(--color-white) 90%
);
/* Shades */
--color-primary--shade-10: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 10%
);
--color-primary--shade-20: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 20%
);
--color-primary--shade-30: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 30%
);
--color-primary--shade-40: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 40%
);
--color-primary--shade-50: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 50%
);
--color-primary--shade-60: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 60%
);
--color-primary--shade-70: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 70%
);
--color-primary--shade-80: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 80%
);
--color-primary--shade-90: color-mix(
in srgb,
var(--color-primary),
var(--color-black) 90%
);
/* Opacity */
--color-primary--transparency-10: color-mix(
in srgb,
var(--color-primary),
transparent 10%
);
--color-primary--transparency-20: color-mix(
in srgb,
var(--color-primary),
transparent 20%
);
--color-primary--transparency-30: color-mix(
in srgb,
var(--color-primary),
transparent 30%
);
--color-primary--transparency-40: color-mix(
in srgb,
var(--color-primary),
transparent 40%
);
--color-primary--transparency-50: color-mix(
in srgb,
var(--color-primary),
transparent 50%
);
--color-primary--transparency-60: color-mix(
in srgb,
var(--color-primary),
transparent 60%
);
--color-primary--transparency-70: color-mix(
in srgb,
var(--color-primary),
transparent 70%
);
--color-primary--transparency-80: color-mix(
in srgb,
var(--color-primary),
transparent 80%
);
--color-primary--transparency-90: color-mix(
in srgb,
var(--color-primary),
transparent 90%
);
--color-primary--transparency-95: color-mix(
in srgb,
var(--color-primary),
transparent 95%
);
/* Neutral Grey Stack */
--color-neutral-10: color-mix(
in srgb,
var(--color-black) 10%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-20: color-mix(
in srgb,
var(--color-black) 20%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-30: color-mix(
in srgb,
var(--color-black) 30%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-40: color-mix(
in srgb,
var(--color-black) 40%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-50: color-mix(
in srgb,
var(--color-black) 50%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-60: color-mix(
in srgb,
var(--color-black) 60%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-70: color-mix(
in srgb,
var(--color-black) 70%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-80: color-mix(
in srgb,
var(--color-black) 80%,
var(--color-primary) var(--neutral-percentage)
);
--color-neutral-90: color-mix(
in srgb,
var(--color-black) 90%,
var(--color-primary) var(--neutral-percentage)
);
// spacing variables
--space-3xs: clamp(0.25rem, 0.232rem + 0.0901vw, 0.3125rem);
--space-2xs: clamp(0.5rem, 0.464rem + 0.1802vw, 0.625rem);
--space-xs: clamp(0.75rem, 0.6959rem + 0.2703vw, 0.9375rem);
--space-s: clamp(1rem, 0.9279rem + 0.3604vw, 1.25rem);
--space-m: clamp(1.5rem, 1.3919rem + 0.5405vw, 1.875rem);
--space-l: clamp(2rem, 1.8559rem + 0.7207vw, 2.5rem);
}
// Mixin to generate CSS custom properties
@mixin generate-color-variables($color-name, $base-color, $steps: 9) {
:root {
// Generate tints
@for $i from 1 through $steps {
--#{$color-name}--tint-#{$i * 10}: color-mix(
in srgb,
var(--#{$base-color}),
var(--color-white) #{$i * 10}%
);
}
// Generate shades
@for $i from 1 through $steps {
--#{$color-name}--shade-#{$i * 10}: color-mix(
in srgb,
var(--#{$base-color}),
var(--color-black) #{$i * 10}%
);
}
// Generate opacities
@for $i from 1 through $steps {
--#{$color-name}--transparency-#{$i * 10}: color-mix(
in srgb,
var(--#{$base-color}),
transparent #{$i * 10}%
);
}
// Generate grayscale
@for $i from 1 through $steps {
--neutral-#{$i * 10}: color-mix(
in srgb,
var(--color-black) #{$i * 10}%,
var(--color-primary) var(--neutral-percentage, 3%)
);
}
}
}
// Usage
// @include generate-color-variables("color-primary", "color-primary", 10);
.visually-hidden:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
#neutral-percentage {
width: 100%;
}
#neutral-value {
font-weight: bold;
}
html {
background-color: #f5f5f5;
}
body {
container-type: inline-size;
font-family: "IBM Plex Mono", monospace;
font-weight: 400;
margin: var(--space-m);
}
h1 {
font-family: "Anek Latin", sans-serif;
font-weight: 800;
letter-spacing: 0.125rem;
color: var(--color-black);
border-bottom: 1px solid var(--color-neutral-20);
padding-bottom: var(--space-2xs);
margin-bottom: var(--space-m);
}
form {
display: flex;
align-items: center;
font-weight: 600;
gap: var(--space-3xs);
accent-color: #848884;
.no-color-picker & {
display: none;
}
@media (min-width: 660px) {
margin-left: var(--space-s);
}
}
label {
font-size: 1.25rem;
font-family: "Anek Latin", sans-serif;
}
input {
width: 48px;
height: 48px;
@supports (appearance: color-picker) {
background-color: red !important;
display: none;
}
}
.palette {
display: grid;
padding: var(--space-s);
background-color: #e5e5e5;
border-radius: var(--space-xs);
margin-top: 1rem;
gap: var(--space-s);
@container (min-width: 500px) {
grid-template-columns: 1fr 1fr;
}
@container (min-width: 1100px) {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
.palette-group {
border-radius: var(--space-xs);
container-type: inline-size;
z-index: 1;
}
.palette-group h2 {
grid-column: 1 / -1;
flex: 1 1 100%;
}
h2,
.key summary {
font-size: 1.5rem;
margin-bottom: 1rem;
font-family: "Anek Latin", sans-serif;
font-weight: 700;
letter-spacing: 0.125rem;
}
.color-block {
display: grid;
grid-template-columns: auto max-content;
grid-template-areas: "swatch text";
gap: 0.5rem var(--space-s);
}
.color-swatch {
grid-area: swatch;
width: 100%;
height: 100%;
margin-bottom: var(--space-xs);
}
.palette-group--transparency .color-block {
.color-swatch {
position: relative;
overflow: hidden;
&::before,
&::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
width: 50%;
height: 100%;
z-index: -1;
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 28" width="56" height="28"%3E%3Cpath fill="%239C92AC" fill-transparency=".5" d="M56 26v2h-7.75c2.3-1.27 4.94-2 7.75-2zm-26 2a2 2 0 1 0-4 0h-4.09A25.98 25.98 0 0 0 0 16v-2c.67 0 1.34.02 2 .07V14a2 2 0 0 0-2-2v-2a4 4 0 0 1 3.98 3.6 28.09 28.09 0 0 1 2.8-3.86A8 8 0 0 0 0 6V4a9.99 9.99 0 0 1 8.17 4.23c.94-.95 1.96-1.83 3.03-2.63A13.98 13.98 0 0 0 0 0h7.75c2 1.1 3.73 2.63 5.1 4.45 1.12-.72 2.3-1.37 3.53-1.93A20.1 20.1 0 0 0 14.28 0h2.7c.45.56.88 1.14 1.29 1.74 1.3-.48 2.63-.87 4-1.15-.11-.2-.23-.4-.36-.59H26v.07a28.4 28.4 0 0 1 4 0V0h4.09l-.37.59c1.38.28 2.72.67 4.01 1.15.4-.6.84-1.18 1.3-1.74h2.69a20.1 20.1 0 0 0-2.1 2.52c1.23.56 2.41 1.2 3.54 1.93A16.08 16.08 0 0 1 48.25 0H56c-4.58 0-8.65 2.2-11.2 5.6 1.07.8 2.09 1.68 3.03 2.63A9.99 9.99 0 0 1 56 4v2a8 8 0 0 0-6.77 3.74c1.03 1.2 1.97 2.5 2.79 3.86A4 4 0 0 1 56 10v2a2 2 0 0 0-2 2.07 28.4 28.4 0 0 1 2-.07v2c-9.2 0-17.3 4.78-21.91 12H30zM7.75 28H0v-2c2.81 0 5.46.73 7.75 2zM56 20v2c-5.6 0-10.65 2.3-14.28 6h-2.7c4.04-4.89 10.15-8 16.98-8zm-39.03 8h-2.69C10.65 24.3 5.6 22 0 22v-2c6.83 0 12.94 3.11 16.97 8zm15.01-.4a28.09 28.09 0 0 1 2.8-3.86 8 8 0 0 0-13.55 0c1.03 1.2 1.97 2.5 2.79 3.86a4 4 0 0 1 7.96 0zm14.29-11.86c1.3-.48 2.63-.87 4-1.15a25.99 25.99 0 0 0-44.55 0c1.38.28 2.72.67 4.01 1.15a21.98 21.98 0 0 1 36.54 0zm-5.43 2.71c1.13-.72 2.3-1.37 3.54-1.93a19.98 19.98 0 0 0-32.76 0c1.23.56 2.41 1.2 3.54 1.93a15.98 15.98 0 0 1 25.68 0zm-4.67 3.78c.94-.95 1.96-1.83 3.03-2.63a13.98 13.98 0 0 0-22.4 0c1.07.8 2.09 1.68 3.03 2.63a9.99 9.99 0 0 1 16.34 0z"%3E%3C/path%3E%3C/svg%3E');
}
&::before {
background-color: var(--color-white);
left: 0;
}
&::after {
background-color: var(--color-black);
right: 0;
}
}
}
.percentage {
text-align-last: left;
grid-area: text;
font-size: 1em;
line-height: 2.5;
font-family: "IBM Plex Mono", monospace;
span {
display: none;
}
@container (min-width: 360px) {
span {
display: inline;
}
}
}
pre {
grid-column: 1 / -1;
padding: var(--space-s);
border-radius: var(--space-xs);
background-color: #d5d5d5;
overflow: scroll;
position: relative; /* Ensure the button is positioned relative to the <pre> */
}
.copy-btn {
position: absolute;
top: 1rem;
right: 1rem;
padding: var(--space-2xs) var(--space-l);
border: 1px solid var(--color-black);
font-size: 1em;
font-family: inherit;
font-family: "Anek Latin", sans-serif;
font-weight: 600;
color: white;
background-color: #000;
border-radius: var(--space-2xs);
cursor: pointer;
transition: all 0.2s ease-in-out;
}
.copy-btn:hover {
background-color: var(--color-white);
color: var(--color-black);
border: 1px solid var(--color-black);
}
@mixin generate-color-tints($color-name, $tint-start, $tint-end) {
@for $i from $tint-start through $tint-end {
.color-block[data-color="--#{$color-name}--tint-#{$i}"] .color-swatch {
background-color: var(--#{$color-name}--tint-#{$i});
}
}
}
// Usage
@include generate-color-tints("color-primary", 10, 90);
/* Shades */
.color-block[data-color="--color-primary--shade-10"] .color-swatch {
background-color: var(--color-primary--shade-10);
}
.color-block[data-color="--color-primary--shade-20"] .color-swatch {
background-color: var(--color-primary--shade-20);
}
.color-block[data-color="--color-primary--shade-30"] .color-swatch {
background-color: var(--color-primary--shade-30);
}
.color-block[data-color="--color-primary--shade-40"] .color-swatch {
background-color: var(--color-primary--shade-40);
}
.color-block[data-color="--color-primary--shade-50"] .color-swatch {
background-color: var(--color-primary--shade-50);
}
.color-block[data-color="--color-primary--shade-60"] .color-swatch {
background-color: var(--color-primary--shade-60);
}
.color-block[data-color="--color-primary--shade-70"] .color-swatch {
background-color: var(--color-primary--shade-70);
}
.color-block[data-color="--color-primary--shade-80"] .color-swatch {
background-color: var(--color-primary--shade-80);
}
.color-block[data-color="--color-primary--shade-90"] .color-swatch {
background-color: var(--color-primary--shade-90);
}
/* Opacities */
.color-block[data-color="--color-primary--transparency-10"] .color-swatch {
background-color: var(--color-primary--transparency-10);
}
.color-block[data-color="--color-primary--transparency-20"] .color-swatch {
background-color: var(--color-primary--transparency-20);
}
.color-block[data-color="--color-primary--transparency-30"] .color-swatch {
background-color: var(--color-primary--transparency-30);
}
.color-block[data-color="--color-primary--transparency-40"] .color-swatch {
background-color: var(--color-primary--transparency-40);
}
.color-block[data-color="--color-primary--transparency-50"] .color-swatch {
background-color: var(--color-primary--transparency-50);
}
.color-block[data-color="--color-primary--transparency-60"] .color-swatch {
background-color: var(--color-primary--transparency-60);
}
.color-block[data-color="--color-primary--transparency-70"] .color-swatch {
background-color: var(--color-primary--transparency-70);
}
.color-block[data-color="--color-primary--transparency-80"] .color-swatch {
background-color: var(--color-primary--transparency-80);
}
.color-block[data-color="--color-primary--transparency-90"] .color-swatch {
background-color: var(--color-primary--transparency-90);
}
.color-block[data-color="--color-primary--transparency-95"] .color-swatch {
background-color: var(--color-primary--transparency-95);
}
// Neutrals
.color-block[data-color="--color-neutral-10"] .color-swatch {
background-color: var(--color-neutral-10);
}
.color-block[data-color="--color-neutral-20"] .color-swatch {
background-color: var(--color-neutral-20);
}
.color-block[data-color="--color-neutral-30"] .color-swatch {
background-color: var(--color-neutral-30);
}
.color-block[data-color="--color-neutral-40"] .color-swatch {
background-color: var(--color-neutral-40);
}
.color-block[data-color="--color-neutral-50"] .color-swatch {
background-color: var(--color-neutral-50);
}
.color-block[data-color="--color-neutral-60"] .color-swatch {
background-color: var(--color-neutral-60);
}
.color-block[data-color="--color-neutral-70"] .color-swatch {
background-color: var(--color-neutral-70);
}
.color-block[data-color="--color-neutral-80"] .color-swatch {
background-color: var(--color-neutral-80);
}
.color-block[data-color="--color-neutral-90"] .color-swatch {
background-color: var(--color-neutral-90);
}
.color-block[data-color="--color-neutral-100"] .color-swatch {
background-color: var(--color-neutral-100);
}
.form-item {
display: flex;
gap: var(--space-3xs);
align-items: center;
}
.palette-group__header {
display: grid;
grid-template-columns: max-content 1fr;
height: 52px;
align-items: center;
}
.palette-group--neutral {
.palette-group__header {
align-items: end;
gap: var(--space-2xs);
}
h2 {
grid-column: span 1;
}
}
.form-item {
display: flex;
align-items: center;
}
.pick-a-color {
position: sticky;
top: 0;
background-color: #f5f5f5;
z-index: 9999;
width: 100%;
}
.copy-btn {
outline: 1px solid var(--color-black);
outline-offset: 2px;
}
.no-js {
.copy-btn {
display: none;
}
form {
display: none;
}
}
.key {
grid-column: 1 / -1;
}
ul {
font-family: "Anek Latin", sans-serif;
font-size: 1.125rem;
li + li {
margin-top: var(--space-2xs);
}
}
b {
font-weight: 900;
}
.original-post {
padding: var(--space-l) var(--space-s);
width: 100%;
background-color: #ccc;
margin-top: var(--space-2xs);
border-radius: 1rem;
p {
font-weight: 600;
font-size: 1.5rem;
color: black;
text-align: center;
}
p + p {
margin-top: var(--space-m);
}
a {
color: inherit;
}
}
View Compiled
// Constants for default values
const DEFAULT_COLOR = "#ff7f00";
const DEFAULT_NEUTRAL_PERCENTAGE = 3;
// Function to update the CSS code block dynamically
function updateCodeBlock(baseColor, neutralPercentage) {
const codeBlock = document.querySelector("pre code.language-css");
if (codeBlock) {
// Regular expressions for updating the base color and neutral percentages
const baseColorRegex = /(--color-primary:\s)#([0-9a-fA-F]{6}|[0-9a-fA-F]{3});/;
const neutralRegex = /(--color-neutral-\d+: color-mix\(in srgb, var\(--color-black\) \d+%, var\(--color-primary\) )\d+%(\);)/g;
// Replace base color in the CSS code block
let updatedCSS = codeBlock.textContent.replace(
baseColorRegex,
`$1${baseColor};`
);
// Replace neutral percentages dynamically in the CSS code block
updatedCSS = updatedCSS.replace(
neutralRegex,
(_, prefix, suffix) => `${prefix}${neutralPercentage}%${suffix}`
);
// Update the text content of the code block
codeBlock.textContent = updatedCSS;
}
}
// Function to update the CSS custom property for neutral percentage
function updateNeutralPercentage(value) {
// Update the custom property in the document's root
document.documentElement.style.setProperty(
"--neutral-percentage",
`${value}%`
);
// Update the displayed value of the slider
document.getElementById("neutral-value").textContent = `${value}%`;
// Get the current base color
const baseColor =
document.documentElement.style.getPropertyValue("--color-primary") ||
DEFAULT_COLOR;
// Update the code block with the new values
updateCodeBlock(baseColor, value);
}
// Initialize event listeners and setup on page load
document.addEventListener("DOMContentLoaded", () => {
const colorInput = document.getElementById("base-color");
const neutralSlider = document.getElementById("neutral-percentage");
const copyButton = document.querySelector(".copy-btn");
// Set the initial CSS variables
document.documentElement.style.setProperty("--color-primary", DEFAULT_COLOR);
document.documentElement.style.setProperty(
"--neutral-percentage",
`${DEFAULT_NEUTRAL_PERCENTAGE}%`
);
// Update the code block with initial values
updateCodeBlock(DEFAULT_COLOR, DEFAULT_NEUTRAL_PERCENTAGE);
// Event listener for the color input
colorInput.addEventListener("input", (event) => {
const newColor = event.target.value;
// Update the custom property for the base color
document.documentElement.style.setProperty("--color-primary", newColor);
// Get the current neutral percentage
const neutralPercentage =
document.documentElement.style.getPropertyValue("--neutral-percentage") ||
DEFAULT_NEUTRAL_PERCENTAGE;
// Update the code block with the new base color and current neutral percentage
updateCodeBlock(newColor, parseInt(neutralPercentage));
});
// Event listener for the neutral percentage slider
neutralSlider.addEventListener("input", (event) => {
updateNeutralPercentage(event.target.value);
});
// Copy to clipboard functionality
copyButton.addEventListener("click", () => {
const codeBlock = document.querySelector("pre code.language-css");
if (codeBlock) {
navigator.clipboard
.writeText(codeBlock.textContent)
.then(() => {
copyButton.textContent = "Copied!";
setTimeout(() => (copyButton.textContent = "Copy"), 2000);
})
.catch(() => {
alert("Failed to copy. Please try again.");
});
}
});
});
This Pen doesn't use any external JavaScript resources.