Vanilla Colorful Color Picker
vanilla-colorful is a lightweight, framework-agnostic color picker library implemented as W3C standards-based Custom Elements. It serves as a vanilla JavaScript port of the popular `react-colorful` library, offering the same core functionality in a dependency-free, highly optimized package. The current stable version is 0.7.2, released in November 2022, and while no explicit release cadence is stated, it appears to be actively maintained. Key differentiators include its extremely small bundle size (just 2.7 KB minified and gzipped), 100% test coverage, full TypeScript typings, and comprehensive accessibility (WAI-ARIA) and mobile support. It provides various color picker types (HEX, RGB, HSL, HSV) directly usable as HTML custom elements, making integration into any web application or framework straightforward.
Common errors
-
Uncaught SyntaxError: Cannot use import statement outside a module
cause The HTML `<script>` tag is missing `type="module"` when using ES Module imports directly in the browser.fixAdd `type="module"` to your script tag: `<script type="module" src="./main.js"></script>` or use a bundler/CDN with module resolution. -
Uncaught ReferenceError: HexColorPicker is not defined
cause The JavaScript file is attempting to use `HexColorPicker` (or other custom element classes) without first importing the `vanilla-colorful` module to register the custom elements.fixEnsure `import 'vanilla-colorful';` is at the top of your module, or `import { HexColorPicker } from 'vanilla-colorful';` if you're directly using the class. -
DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "hex-color-picker" has already been used with this registry
cause The `vanilla-colorful` module is being imported and executed multiple times in the same context, attempting to define the same custom element twice.fixEnsure the `import 'vanilla-colorful';` statement runs only once. This can happen if you include the script multiple times, or if a build process duplicates module imports. Remove redundant imports.
Warnings
- breaking Starting with version 0.7.0, setting the `color` property programmatically on a picker component will no longer fire the `color-changed` event. This was changed to prevent infinite loops in reactive frameworks.
- breaking In version 0.6.0, internal elements were simplified and the `color-changed` event typings were added. This might affect advanced users extending internal components or relying on previous internal structures.
- breaking Version 0.5.0 introduced the use of Shadow DOM for the `hex-input` component. This affects how styling is applied to this specific input.
- gotcha The library uses ES Modules and 'bare module specifiers' (e.g., `import 'vanilla-colorful';`). In browsers without `import maps` support, you will need a build tool (like Vite, Rollup, webpack) or a CDN with a module resolver (e.g., unpkg.com with `?module`) to resolve these imports.
- gotcha As a Custom Elements-based library, `vanilla-colorful` relies on modern browser support for Web Components. Older browsers (e.g., Internet Explorer) are not supported without polyfills.
- gotcha Event listeners for color changes are dispatched as `CustomEvent` with the name `color-changed`. The updated color value is available in `event.detail.value`. Frameworks often have their own syntax for listening to custom events.
Install
-
npm install vanilla-colorful -
yarn add vanilla-colorful -
pnpm add vanilla-colorful
Imports
- Side-effect import for custom element registration
const vanillaColorful = require('vanilla-colorful');import 'vanilla-colorful';
- HexColorPicker class
import HexColorPicker from 'vanilla-colorful';
import { HexColorPicker } from 'vanilla-colorful'; - ColorChangeEvent type
import type { ColorChangeEvent } from 'vanilla-colorful';
Quickstart
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vanilla Colorful Quickstart</title>
<style>
body {
font-family: -apple-system, BlinkMacMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
output {
display: block;
margin-top: 10px;
font-size: 1.5rem;
font-weight: bold;
text-align: center;
padding: 10px 20px;
border-radius: 5px;
border: 1px solid #ddd;
background-color: white;
}
</style>
<script type="module" src="./main.js"></script>
</head>
<body>
<div class="wrapper">
<h1>Choose a Color</h1>
<hex-color-picker class="my-picker" color="#1e88e5"></hex-color-picker>
<output id="colorOutput"></output>
</div>
</body>
</html>
// main.js
import 'vanilla-colorful';
document.addEventListener('DOMContentLoaded', () => {
const picker = document.querySelector('hex-color-picker.my-picker');
const output = document.getElementById('colorOutput');
// Set initial color output
if (picker && output) {
output.textContent = picker.color;
output.style.color = picker.color; // For text color visualization
}
// Listen for color changes
picker?.addEventListener('color-changed', (event) => {
const newColor = event.detail.value;
if (output) {
output.textContent = newColor;
output.style.color = newColor; // Update text color
console.log('Color changed to:', newColor);
}
});
// Example of programmatically changing the color after some time
setTimeout(() => {
if (picker) {
picker.color = '#ff4500'; // Set new color (e.g., OrangeRed)
console.log('Programmatically set color to:', picker.color);
}
}, 3000);
});