Open-source project
web-padawan/vanilla-colorful avatar
web-padawan/vanilla-colorful

vanilla-colorful is a 2.7 KB color picker that works outside any framework

A tiny color picker custom element for modern web apps (2.7 KB) 🎨

856 stars30 forksTypeScriptMIT

At a glance

What is it?
vanilla-colorful is a custom element port of react-colorful, written in strict TypeScript with no dependencies and a size ceiling enforced by Size Limit. It is MIT licensed, currently at version 0.7.2, and its documentation still refers to browser support as of October 2022.
Who is it for?
vanilla-colorful is a good fit for a project that wants a real color picker in plain HTML, in a stack without React, or in a bundle where every kilobyte is counted, since it ships as a standard custom element with no runtime dependencies and a documented size ceiling. It is the wrong choice for a React codebase that already depends on react-colorful, and it is not a replacement for a native colour input when a plain swatch will do.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 21 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A color picker implemented as a standard custom element

vanilla-colorful is a port of react-colorful to vanilla Custom Elements, and that single sentence explains the whole design. There is no framework runtime underneath, no plugin registration, and no build step required to use it. The element is registered with the browser and works in any page.

The README lists the characteristics of the library. It is small, at 2.7 KB minified and gzipped, with Size Limit enforcing the figure in continuous integration. It is built on standards based Custom Elements. It is written in strict TypeScript with 100 percent test coverage, and it ships with types included. It follows the WAI-ARIA guidelines to support assistive technology, works on touch screens, and has no dependencies at all.

The framework agnostic claim is worth reading carefully. It points at the custom-elements-everywhere project, which is a way to make custom elements behave inside frameworks that do not natively support them. The library itself does not need that, but if you use React, Vue, Svelte or Angular, that is the layer you may need to add on top.

The primary language of the repository is TypeScript, and the tree shows a modern toolchain: rollup.config.js for bundling, eslint.config.js, a web-test-runner.config.js for browser based tests, a .prettierrc, and a package.json whose scripts are wired through wireit rather than being plain shell one liners.

The element exposes a color property and fires a color-changed event

The public API is small, which is the point. The usage example in the README is the whole interface.

html
<hex-color-picker color="#1e88e5"></hex-color-picker>
<script type="module">
  import 'vanilla-colorful';

  const picker = document.querySelector('hex-color-picker');
  picker.addEventListener('color-changed', (event) => {
    // get updated color value
    const newColor = event.detail.value;
  });

  // get current color value
  console.log(picker.color);
</script>

Two ways to interact, and that is all. The initial value comes from the color attribute, the current value is readable from the element's color property, and every change produces a color-changed event whose detail carries the new value.

The event name matters when you wire several pickers or reuse the element, because a single delegated listener on the document can serve all of them. The README does not document whether the element reflects changes back to the attribute, so if you need the markup to stay in sync with the state, verify that in the browser rather than assume it.

The value format follows the color model of the bundle you imported. The default picker works in HEX strings like #ffffff, and the example sets #1e88e5 through the attribute.

Twelve extra bundles, one per color model, each with its own element name

The default format is a HEX string, and for anything else the library ships additional bundles rather than a single configurable component. The README lists them in a table that maps a file to import to the element to use and a value example.

The hex bundle is hex-color-picker.js, using the hex-color-picker element with values like #ffffff. There is a hex-alpha variant, hex-alpha-color-picker.js, whose values look like #ffffff88. The hue models come in HSL, HSLA, HSV and HSVA families, each with a numeric object form and a string form, for example hsl-color-picker.js with the element hsl-color-picker and a value of { h: 0, s: 0, l: 100 }. The RGB family follows the same pattern with rgb-color-picker.js, rgba-color-picker.js and their string variants.

The practical consequence is that picking a color model is a build time decision, not a runtime one. You import the file for the model you want, and you get the element with the matching name. The package.json exports map makes that explicit, listing each bundle as a subpath export alongside the root entry, which points at hex-color-picker.js. There is also a hex-input.js export and a lib/entrypoints pattern, which suggests a lower level entry point for people assembling their own element.

Because each bundle is a separate file, a project that needs two models ships two elements. There is no single build that contains all of them, which is the deliberate trade for the size ceiling.

Install it with npm or load it straight from a CDN

The npm install is one line.

bash
npm install vanilla-colorful --save

The alternative is a module script pointing at a CDN, and the README lists four of them: unpkg.com, Skypack, JSPM and ESM. Each is a single script tag.

html
<script type="module" src="https://unpkg.com/vanilla-colorful?module"></script>

The same pattern works for the other three hosts, with the unpkg variant carrying a module query flag and the others taking the plain package path.

The CDN route is the fastest way to see the picker working, and it is also the one that dodges the bare specifier problem described in the next section, because nothing has to resolve the import name at runtime.

For local development, the demo folder in the repository holds a working page with its own assets, a favicon script and a stylesheet, and index.html sits at the root, so you can open the project and see the element without wiring anything up.

Bare specifiers need import maps or a module aware dev server

The library is authored in ES modules and the examples import it by bare specifier.

html
<script type="module">
  import 'vanilla-colorful';
</script>

Browsers cannot resolve that on their own. The README explains that the HTML Standard has a feature called import maps that would allow bare specifiers to resolve without tools, but states that as of October 2022 import maps were not yet shipped in all browsers, and recommends in the meantime using a tool that supports ES module based development, naming vite, @web/dev-server and wmr. None of those are needed when importing from a CDN.

That October 2022 caveat dates the documentation. The library itself is a current version, 0.7.2 in package.json, and the repository is not archived with the last push on 2026-10-02. But the guidance about import maps still describes the world as it was four years ago, so treat the recommended tooling list as a starting point rather than current advice, and check what your own build tooling already supports.

The package itself declares type as module, with main and module both pointing at hex-color-picker.js, which tells you the distributed bundle is already ESM and needs no transformation in a modern pipeline.

Size is enforced, not just advertised

The 2.7 KB figure is the headline of the project, and the README is clear that it is controlled rather than measured by hand. Size Limit is the tool that runs in continuous integration and fails the build when the budget is exceeded.

The rest of the repository supports that discipline. The build and dist scripts are wired through wireit, which caches and orders tasks, and the sources are compiled by rollup into per model bundles rather than one large file. The test setup uses web-test-runner, so the tests run in a browser rather than in a simulated DOM, which is the right target for a component whose behaviour depends on pointer events and real layout. Coverage is claimed at 100 percent.

Versioning and release notes are handled too, with a .versionrc for the versioning tool and a CHANGELOG.md at the root. The repository publishes no GitHub releases, so the changelog and the package version in package.json are the record of what shipped.

Licensing is MIT with a LICENSE file at the root, and there is an ACKNOWLEDGMENTS file for the credits the port and its assets require. The project is credited to Serhii Kulykov, and the upstream react-colorful project it is ported from is credited in the README.

When a native colour input or react-colorful is the better answer

The plain alternative is the native input. The element type color gives you a colour picker with no JavaScript at all, and on many platforms it opens the operating system picker rather than a canvas and pointer driven widget. It is less pretty and far less configurable, but it is free, accessible and zero bytes of your bundle. If your design can live with the platform control, this library is solving a problem you may not have.

The other alternative is staying inside your framework. If the application is already React, react-colorful is the same idea implemented as a React component, and using it avoids the wrapper layer for custom elements in frameworks that do not understand them natively. The trade is that the React version inherits the framework and ships its own reactivity model, while this port stays framework agnostic and can be dropped into a server rendered page, a static site or a plain script.

The genuine limitations of the port are worth naming. There is no dark mode or theme handling described in the README, no documented keyboard interaction beyond the ARIA claim, no localisation of the interface, and no mention of how the picker behaves under high contrast modes. The element is a canvas style pointer driven widget, which is the kind of thing that needs real accessibility testing rather than a compliance note, and the README does not document how a screen reader user picks a colour.

For a design tool or a settings panel where colour accuracy matters, that is worth verifying before you ship it.

Editorial conclusion

vanilla-colorful is a good fit for a project that wants a real color picker in plain HTML, in a stack without React, or in a bundle where every kilobyte is counted, since it ships as a standard custom element with no runtime dependencies and a documented size ceiling. It is the wrong choice for a React codebase that already depends on react-colorful, and it is not a replacement for a native colour input when a plain swatch will do. Before adopting it, check the entry point you import, since each color model has its own file and its own element name, and read the CHANGELOG.md rather than assuming the tagged version matches package.json, because the repository publishes no GitHub releases.

Frequently asked questions

How do I install vanilla-colorful?

Run npm install vanilla-colorful --save, or load it as a module script from a CDN such as unpkg.com, Skypack, JSPM or ESM. The package ships ES modules with main and module pointing at hex-color-picker.js.

How do I get the selected color in vanilla-colorful?

Read the element's color property for the current value and listen for the color-changed event, whose detail carries the updated value. The initial value is set through the color attribute on the element.

Can I use vanilla-colorful with HSL or RGB values?

Yes, but each color model has its own bundle and element name. The exports map in package.json lists hex, hex-alpha, hsl, hsla, hsv, hsva, rgb and rgba variants, each in an object form and a string form.

Does vanilla-colorful work with React or Vue?

The README describes it as framework agnostic, since it is built on standard Custom Elements, and points at the custom-elements-everywhere project for frameworks that do not support custom elements natively. Live examples are provided for Angular, Lit, React, Svelte and Vue.

How large is vanilla-colorful and how is that enforced?

The README states a size of 2.7 KB minified and gzipped, and says Size Limit controls the size in continuous integration. The project also claims 100 percent test coverage and ships with TypeScript types included.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. web-padawan/vanilla-colorful on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/web-padawan-vanilla-colorful.svg)](https://hysenlabs.com/projects/web-padawan-vanilla-colorful)

Was this useful?