Color Picker
Here we are using 3 sliders for the hue, saturation and lightness values.
The color is then calculated using the hsl()
function and
placed into the style=""
property as a css variable.
<script>
let color = { h: 40, s: 50, l: 90 };
$: styles = `
--hue: ${color.h}deg;
--saturation: ${color.s}%;
--lightness: ${color.l}%;
--color: hsl( var(--hue), var(--saturation), var(--lightness) );
--picker-color: hsla( var(--hue), 60%, 70%, 1 );
`;
</script>
<div class="color-ui" style="{styles}">
<RangeSlider id="h" float prefix="h: " suffix="°" bind:value={color.h} max={360} />
<RangeSlider id="s" float prefix="s: " suffix="%" bind:value={color.s} max={100} />
<RangeSlider id="l" float prefix="l: " suffix="%" bind:value={color.l} max={100} />
{#if styles}
<div class="color">
--hue: {color.h}deg;
--saturation: {color.s}%;
--lightness: {color.l}%;
</div>
{/if}
</div>
/** border and frame for the color ui */
.color {
padding: 1em;
background-color: var(--color);
transition: all 0.5s ease;
}
/** color picker slider */
.color-ui .rangeSlider.rangeSlider {
margin-block: 2em;
/* replace the default accent colors with the color from JS */
--slider-accent: var(--picker-color);
--slider-accent-100: var(--picker-color);
}
/** always show the floating values, and place them over the handles */
.color-ui .rangeSlider.rangeSlider .rangeFloat,
.color-ui .rangeSlider.rangeSlider.rsFocus .rangeFloat,
.color-ui .rangeSlider.rangeSlider:hover .rangeFloat {
opacity: 1;
translate: -50% 100%;
border-radius: 1em;
padding: .5em .75em;
pointer-events: all;
}
/** Simple Styling for the outer UI */
.color-ui {
border-radius: 0.5rem;
border: 2px solid var(--color);
color: var(--color);
transition: all 0.5s ease;
user-select: none;
font-family: var(--font-mono);
}
/** Advanced css to invert the text color and add a vibrant shadow */
.color-ui {
color: hsla(var(--hue), calc( var(--saturation) / 2),calc( (var(--lightness ) - 50%) * -1 + 100% ), 1);
text-shadow: 0 1px 1px hsla(var(--hue), calc( var(--saturation) / 2),calc( var(--lightness ) - 50% ), 1);
box-shadow:
0 1px 1px 2px hsla(var(--hue), calc( var(--saturation) / 2), max( calc( var(--lightness ) - 10% ), 30% ), 1),
0 4px 4px 1px hsla(var(--hue), calc( var(--saturation) / 2), max( calc( var(--lightness ) - 10% ), 30% ), .5),
0 8px 10px 5px hsla(var(--hue), calc( var(--saturation) / 2), max( calc( var(--lightness ) - 10% ), 30% ), .5);
}
.color-ui #h.rangeSlider {
--s: var(--saturation);
--l: var(--lightness);
background-image: linear-gradient(to right, hsl(0, var(--s), var(--l)), hsl(60, var(--s), var(--l)), hsl(120, var(--s), var(--l)), hsl(180, var(--s), var(--l)), hsl(240, var(--s), var(--l)), hsl(300, var(--s), var(--l)), hsl(360, var(--s), var(--l)));
}
.color-ui #s.rangeSlider {
--h: var(--hue);
--l: var(--lightness);
background-image: linear-gradient(to right, hsl(var(--h), 0%, var(--l)), hsl(var(--h), 100%, var(--l)));
}
.color-ui #l.rangeSlider {
--h: var(--hue);
--s: var(--saturation);
background-image: linear-gradient(to right, hsl(var(--h), var(--s), 0%), hsl(var(--h), var(--s), 50%), hsl(var(--h), var(--s), 100%));
}