Color Picker Rails Components

Add color selection functionality to your forms with native HTML5 color inputs, enhanced color pickers with swatches, and advanced third-party solutions. Perfect for theme customization, design tools, and user preferences.

Installation

1. Shoelace Color Picker

For advanced color picker features, you can use Shoelace's color picker component. :

<!-- Shoelace --> <script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/components/color-picker/color-picker.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/light.css" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/dark.css" /> 

2. Shoelace Styling

If you want to have more neutral accent colors instead of the default blue & more rounded corners, you can use the following CSS to style the Shoelace color picker:

/* Shoelace Neutral styles */ :root { --sl-color-primary-50: var(--sl-color-neutral-50) !important; --sl-color-primary-100: var(--sl-color-neutral-100) !important; --sl-color-primary-200: var(--sl-color-neutral-200) !important; --sl-color-primary-300: var(--sl-color-neutral-300) !important; --sl-color-primary-400: var(--sl-color-neutral-400) !important; --sl-color-primary-500: var(--sl-color-neutral-500) !important; --sl-color-primary-600: var(--sl-color-neutral-600) !important; --sl-color-primary-700: var(--sl-color-neutral-700) !important; --sl-color-primary-800: var(--sl-color-neutral-800) !important; --sl-color-primary-900: var(--sl-color-neutral-900) !important; --sl-color-primary-950: var(--sl-color-neutral-950) !important; --sl-input-focus-ring-color: hsla(0, 0%, 81%, 0.4) !important; --sl-border-radius-medium: 0.5rem !important; --sl-border-radius-large: 0.75rem !important; }

Shoelace Examples

Enhanced color picker

Shoelace color picker with a modern interface, color format display, and copy functionality.

Current value: #3b82f6
<%# Shoelace Color Picker %> <%# Note: This requires Shoelace %> <div class="space-y-4"> <div class="flex flex-col items-center gap-2"> <sl-color-picker label="Brand Color" value="#3b82f6" format="hex" size="medium" id="enhanced-picker" ></sl-color-picker> </div> <div class="flex justify-center items-center gap-3 text-sm"> <span class="text-neutral-600 dark:text-neutral-400">Current value:</span> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" id="enhanced-value">#3b82f6</code> </div> </div> <script> // Handle color picker changes with Turbo support document.addEventListener('turbo:load', function() { const enhancedPicker = document.getElementById('enhanced-picker'); const enhancedValue = document.getElementById('enhanced-value'); const copyButton = document.getElementById('copy-color'); if (enhancedPicker) { enhancedPicker.addEventListener('sl-change', function(e) { enhancedValue.textContent = e.target.value; }); } }); </script>

Color picker with opacity

Advanced color picker with alpha channel support for transparency control.

Hex (with alpha): #f5a623ff
RGBA: rgba(245, 166, 35, 1)

Preview:

<%# Shoelace Color Picker with Opacity/Alpha Channel %> <div class="space-y-4"> <div class="flex flex-col items-center gap-2"> <sl-color-picker label="Background Color" value="#f5a623ff" opacity format="hex" no-format-toggle size="medium" id="opacity-picker" ></sl-color-picker> </div> <div class="flex flex-col gap-2"> <div class="flex items-center gap-3 text-sm"> <span class="text-neutral-600 dark:text-neutral-400">Hex (with alpha):</span> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" id="hex-alpha-value">#f5a623ff</code> </div> <div class="flex items-center gap-3 text-sm"> <span class="text-neutral-600 dark:text-neutral-400">RGBA:</span> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" id="rgba-value">rgba(245, 166, 35, 1)</code> </div> </div> <%# Preview with transparency %> <div class="space-y-2"> <p class="text-sm font-medium text-neutral-700 dark:text-neutral-300 text-center">Preview:</p> <div class="relative h-24 rounded-lg overflow-hidden outline-1 -outline-offset-1 outline-black/15 dark:outline-white/20"> <%# Checkerboard background to show transparency %> <div class="absolute inset-0 checkerboard-bg opacity-20"></div> <div class="absolute inset-0" id="color-preview" style="background-color: #f5a623ff" ></div> </div> </div> </div> <script> // Handle opacity picker changes with Turbo support document.addEventListener('turbo:load', function() { const opacityPicker = document.getElementById('opacity-picker'); const hexAlphaValue = document.getElementById('hex-alpha-value'); const rgbaValue = document.getElementById('rgba-value'); const colorPreview = document.getElementById('color-preview'); if (opacityPicker) { opacityPicker.addEventListener('sl-change', function(e) { const color = e.target.value; hexAlphaValue.textContent = color; // Convert to RGBA for display const r = parseInt(color.slice(1, 3), 16); const g = parseInt(color.slice(3, 5), 16); const b = parseInt(color.slice(5, 7), 16); const a = color.length > 7 ? (parseInt(color.slice(7, 9), 16) / 255).toFixed(2) : '1'; rgbaValue.textContent = `rgba(${r}, ${g}, ${b}, ${a})`; colorPreview.style.backgroundColor = color; }); } }); </script> <style> /* Checkerboard pattern for transparency background */ .checkerboard-bg { background-image: linear-gradient(45deg, #e5e7eb 25%, transparent 25%), linear-gradient(-45deg, #e5e7eb 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #e5e7eb 75%), linear-gradient(-45deg, transparent 75%, #e5e7eb 75%); background-size: 20px 20px; background-position: 0 0, 0 10px, 10px -10px, -10px 0px; } /* Dark mode checkerboard */ .dark .checkerboard-bg { background-image: linear-gradient(45deg, #374151 25%, transparent 25%), linear-gradient(-45deg, #374151 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #374151 75%), linear-gradient(-45deg, transparent 75%, #374151 75%); } </style>

Color format variations

Color pickers configured for different color format outputs: HEX, RGB, HSL, and HSV.

Choose the output format that best suits your needs

Output:
#4a90e2
Output:
rgb(80, 227, 194)
Output:
hsl(290, 87%, 47%)
Output:
hsv(55, 89%, 97%)
<%# Shoelace Color picker with format variations %> <div class="space-y-6"> <p class="text-sm text-neutral-500 dark:text-neutral-400 text-center"> Choose the output format that best suits your needs </p> <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <%# HEX Format %> <div class="space-y-3"> <div class="flex flex-col items-center"> <sl-color-picker label="HEX Format" format="hex" value="#4a90e2" size="small" id="hex-picker" ></sl-color-picker> </div> <div class="text-center"> <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" id="hex-output">#4a90e2</code> </div> </div> <%# RGB Format %> <div class="space-y-3"> <div class="flex flex-col items-center"> <sl-color-picker label="RGB Format" format="rgb" value="rgb(80, 227, 194)" size="small" id="rgb-picker" ></sl-color-picker> </div> <div class="text-center"> <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" id="rgb-output">rgb(80, 227, 194)</code> </div> </div> <%# HSL Format %> <div class="space-y-3"> <div class="flex flex-col items-center"> <sl-color-picker label="HSL Format" format="hsl" value="hsl(290, 87%, 47%)" size="small" id="hsl-picker" ></sl-color-picker> </div> <div class="text-center"> <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" id="hsl-output">hsl(290, 87%, 47%)</code> </div> </div> <%# HSV Format %> <div class="space-y-3"> <div class="flex flex-col items-center"> <sl-color-picker label="HSV Format" format="hsv" value="hsv(55, 89%, 97%)" size="small" id="hsv-picker" ></sl-color-picker> </div> <div class="text-center"> <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div> <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" id="hsv-output">hsv(55, 89%, 97%)</code> </div> </div> </div> </div> <script> // Update output displays for each format with Turbo support document.addEventListener('turbo:load', function() { ['hex', 'rgb', 'hsl', 'hsv'].forEach(format => { const picker = document.getElementById(`${format}-picker`); const output = document.getElementById(`${format}-output`); if (picker && output) { picker.addEventListener('sl-change', function(e) { output.textContent = e.target.value; }); } }); }); </script>

Color picker with custom palette

Enhanced color picker with a custom color palette for consistent brand colors.

Brand Palette

Neutrals

Accents

Selected Color:
#4a5568
<%# Shoelace Color Picker with Custom Brand Palette %> <div class="space-y-6"> <div class="flex flex-col items-center"> <sl-color-picker label="Brand Color" value="#4a5568" swatches="#1a202c; #2d3748; #4a5568; #718096; #a0aec0; #cbd5e0; #e2e8f0; #f7fafc; #fed7d7; #feb2b2; #fc8181; #f56565; #e53e3e; #c53030; #9b2c2c; #742a2a" size="medium" id="brand-picker" ></sl-color-picker> </div> <div class="space-y-4"> <p class="text-sm font-medium text-neutral-600 dark:text-neutral-400 text-center">Brand Palette</p> <div class="space-y-4"> <%# Neutral Colors %> <div class="space-y-2"> <p class="text-xs text-neutral-500 dark:text-neutral-400 uppercase tracking-wide text-center">Neutrals</p> <div class="flex justify-center gap-2 flex-wrap"> <button type="button" data-color="#1a202c" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #1a202c" title="Gray 900"></button> <button type="button" data-color="#2d3748" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #2d3748" title="Gray 800"></button> <button type="button" data-color="#4a5568" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #4a5568" title="Gray 700"></button> <button type="button" data-color="#718096" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #718096" title="Gray 500"></button> <button type="button" data-color="#a0aec0" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #a0aec0" title="Gray 400"></button> <button type="button" data-color="#cbd5e0" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #cbd5e0" title="Gray 300"></button> <button type="button" data-color="#e2e8f0" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #e2e8f0" title="Gray 200"></button> <button type="button" data-color="#f7fafc" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #f7fafc" title="Gray 50"></button> </div> </div> <%# Accent Colors %> <div class="space-y-2"> <p class="text-xs text-neutral-500 dark:text-neutral-400 uppercase tracking-wide text-center">Accents</p> <div class="flex justify-center gap-2 flex-wrap"> <button type="button" data-color="#fed7d7" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #fed7d7" title="Red 100"></button> <button type="button" data-color="#feb2b2" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #feb2b2" title="Red 200"></button> <button type="button" data-color="#fc8181" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #fc8181" title="Red 300"></button> <button type="button" data-color="#f56565" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #f56565" title="Red 400"></button> <button type="button" data-color="#e53e3e" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #e53e3e" title="Red 500"></button> <button type="button" data-color="#c53030" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #c53030" title="Red 600"></button> <button type="button" data-color="#9b2c2c" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #9b2c2c" title="Red 700"></button> <button type="button" data-color="#742a2a" class="brand-swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #742a2a" title="Red 800"></button> </div> </div> </div> </div> <div class="flex flex-col items-center gap-3 p-4 bg-neutral-50 dark:bg-neutral-800/50 rounded-lg border border-neutral-200 dark:border-neutral-700"> <div class="text-sm text-center"> <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Selected Color:</div> <code class="px-2 py-1 bg-white dark:bg-neutral-900 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" id="brand-value">#4a5568</code> </div> <button type="button" class="px-3 py-1.5 text-xs bg-white dark:bg-neutral-900 hover:bg-neutral-50 dark:hover:bg-neutral-800 rounded border border-neutral-300 dark:border-neutral-600 text-neutral-600 dark:text-neutral-400 transition-colors" id="add-to-palette" > Add to Palette </button> </div> </div> <script> // Handle brand picker and swatch interactions with Turbo support document.addEventListener('turbo:load', function() { const brandPicker = document.getElementById('brand-picker'); const brandValue = document.getElementById('brand-value'); const brandSwatches = document.querySelectorAll('.brand-swatch'); const addButton = document.getElementById('add-to-palette'); if (brandPicker) { // Update value display brandPicker.addEventListener('sl-change', function(e) { const color = e.target.value; brandValue.textContent = color; updateBrandSwatchSelection(color); }); } // Handle brand swatch clicks brandSwatches.forEach(swatch => { swatch.addEventListener('click', function() { const color = this.dataset.color; brandPicker.value = color; brandValue.textContent = color; updateBrandSwatchSelection(color); }); }); function updateBrandSwatchSelection(selectedColor) { brandSwatches.forEach(swatch => { if (swatch.dataset.color.toLowerCase() === selectedColor.toLowerCase()) { swatch.classList.remove('ring-transparent'); swatch.classList.add('ring-neutral-500'); } else { swatch.classList.remove('ring-neutral-500'); swatch.classList.add('ring-transparent'); } }); } // Add to palette (example functionality) if (addButton) { addButton.addEventListener('click', function() { const color = brandValue.textContent; console.log('Adding to palette:', color); this.textContent = 'Added!'; setTimeout(() => { this.textContent = 'Add to Palette'; }, 2000); }); } }); </script>

HTML5 Examples

Basic HTML5 color picker

A native HTML5 color input - zero dependencies, works in all modern browsers.

<div class="flex flex-col items-center gap-2"> <label for="basic-color" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1"> Choose a color </label> <input type="color" name="color" id="basic-color" value="#3b82f6" class="size-10 rounded-lg outline-1 -outline-offset-1 outline-black/15 dark:outline-white/20 cursor-pointer hover:scale-105 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" > </div> <style> /* Custom styling for the color input */ input[type="color"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; border: none; } input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0.5rem; } </style>

Color picker with swatches

HTML5 color input with predefined color swatches using datalist. Users can pick from swatches or choose custom colors.

Pick from predefined colors or choose custom

#8b5cf6

Quick select:

<%# Color Picker with Predefined Swatches %> <div class="space-y-4"> <div class="mb-6 relative gap-y-1.5"> <label for="color-with-swatches" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1"> Theme Color </label> <div class="flex items-center gap-3"> <input type="color" name="theme_color" id="color-with-swatches" list="predefined-colors" value="#8b5cf6" class="h-12 w-12 rounded-lg outline-1 -outline-offset-1 outline-black/15 dark:outline-white/20 cursor-pointer hover:scale-105 transition-transform" > <datalist id="predefined-colors"> <option value="#ede9fe">Violet 100</option> <option value="#ddd6fe">Violet 200</option> <option value="#c4b5fd">Violet 300</option> <option value="#a78bfa">Violet 400</option> <option value="#8b5cf6">Violet 500</option> <option value="#7c3aed">Violet 600</option> <option value="#6d28d9">Violet 700</option> <option value="#5b21b6">Violet 800</option> <option value="#4c1d95">Violet 900</option> </datalist> <div class="text-sm"> <p class="text-neutral-600 dark:text-neutral-400">Pick from predefined colors or choose custom</p> <p class="font-mono text-xs text-neutral-500" id="swatch-value">#8b5cf6</p> </div> </div> </div> <%# Visual swatches for quick selection %> <div class="space-y-2"> <p class="text-sm font-medium text-neutral-700 dark:text-neutral-300">Quick select:</p> <div class="flex gap-2 flex-wrap justify-center"> <button type="button" data-color="#ede9fe" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #ede9fe"></button> <button type="button" data-color="#ddd6fe" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #ddd6fe"></button> <button type="button" data-color="#c4b5fd" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #c4b5fd"></button> <button type="button" data-color="#a78bfa" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #a78bfa"></button> <button type="button" data-color="#8b5cf6" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #8b5cf6"></button> <button type="button" data-color="#7c3aed" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #7c3aed"></button> <button type="button" data-color="#6d28d9" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #6d28d9"></button> <button type="button" data-color="#5b21b6" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #5b21b6"></button> <button type="button" data-color="#4c1d95" class="swatch h-8 w-8 rounded-md border border-black/15 dark:border-white/20 hover:scale-110 transition-transform focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200" style="background-color: #4c1d95"></button> </div> </div> </div> <script> // Update value display with Turbo support document.addEventListener('turbo:load', function() { const colorInput = document.getElementById('color-with-swatches'); const valueDisplay = document.getElementById('swatch-value'); const swatches = document.querySelectorAll('.swatch'); if (colorInput && valueDisplay) { colorInput.addEventListener('change', function(e) { valueDisplay.textContent = e.target.value; updateSwatchSelection(e.target.value); }); } // Handle swatch clicks swatches.forEach(swatch => { swatch.addEventListener('click', function() { const color = this.dataset.color; colorInput.value = color; valueDisplay.textContent = color; updateSwatchSelection(color); }); }); // Function to update swatch selection visual feedback function updateSwatchSelection(selectedColor) { swatches.forEach(swatch => { if (swatch.dataset.color.toLowerCase() === selectedColor.toLowerCase()) { swatch.classList.add('ring-2', 'ring-offset-2', 'ring-neutral-500', 'dark:ring-neutral-400'); } else { swatch.classList.remove('ring-2', 'ring-offset-2', 'ring-neutral-500', 'dark:ring-neutral-400'); } }); } // Set initial selection if (colorInput) { updateSwatchSelection(colorInput.value); } }); </script> <style> /* Custom styling for the color input */ input[type="color"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; border: none; padding: 0; } input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; } input[type="color"]::-webkit-color-swatch { border: none; border-radius: 0.5rem; } </style>

Configuration

Color pickers can be implemented using native HTML5 inputs or enhanced with third-party libraries for additional features.

Native HTML5 Color Input

The simplest approach with zero dependencies:

<input type="color" name="color" id="color" value="#3b82f6" class="...">

With Predefined Colors

Add a datalist for quick color selection:

<input type="color" list="colors" name="theme_color" value="#8b5cf6"> <datalist id="colors"> <option value="#8b5cf6">Purple</option> <option value="#3b82f6">Blue</option> <option value="#10b981">Green</option> </datalist>

Shoelace Color Picker Options

Available attributes for Shoelace color picker customization:

Attribute Default Description
value #ffffff The current color value
format hex Output format: hex, rgb, hsl, or hsv
opacity false Show opacity slider for alpha channel
swatches "" Custom color swatches (semicolon-separated)
label "" Label text for the color picker
size medium Size variant: small, medium, or large

JavaScript Events

Handle color selection events:

// Native color input document.querySelector('input[type="color"]').addEventListener('change', (e) => { console.log('Selected color:', e.target.value); }); // Shoelace color picker document.querySelector('sl-color-picker').addEventListener('sl-change', (e) => { console.log('Color changed:', e.target.value); });

Accessibility

  • Keyboard Support: Native color inputs are keyboard accessible
  • Screen Readers: Use proper labels and aria-labels
  • Color Contrast: Ensure selected colors meet WCAG contrast requirements

Browser Support

  • Native HTML5: Supported in all modern browsers
  • Shoelace: Requires modern browsers with Web Components support
  • Fallback: Consider text input fallback for older browsers

Table of contents