svelte-awesome-color-picker

highly customizable color picker component library

  • 🎹 built-in keyboard navigation
  • 📱 mobile support
  • 🤸‍♂️ accessibility information
  • 🤯 works without javascript (fallback to the browser default color picker)
  • 🏇 it’s compatible with form libraries
  • 🧩 fully customizable
  • 🔨 full typescript support
  • đź–¤ dark theme support

The library uses 2 libraries:

  • colord: lightest color conversion library on the market at the time and supports a11y contrasts
  • svelte-awesome-slider: another library I crafted and is higlhy customizable.

This documentation is the documentation of svelte-awesome-color-picker v4, rewritten in Svelte 5. If you are looking to upgrate to v4, see the section upgrade from v3 to v4. If you are looking for the v3 documentation, you may go through the markdown files of the repo.

Install

npm i -D svelte-awesome-color-picker

The same documentation can be seen on Github, on the npm registry or on the documentation site. I would suggest to visite the documentation site since it has interactive examples!

Examples

Default layout

Source code

<script>
	import ColorPicker from 'svelte-awesome-color-picker';
</script>

<ColorPicker
	bind:hex
	bind:rgb
	bind:hsv
	bind:color
  position="responsive"
/>

Color props

let hex = "#f6f0dc"

let rgb = undefined;

let hsv = undefined;

let color = "// instance of Colord"

Chrome variant

Source code

<script>
	import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
</script>

<ColorPicker bind:rgb bind:hsv bind:hex components={ChromeVariant} sliderDirection="horizontal" />

Accessibility notice variant

Source code

<script>
	import ColorPicker, { A11yVariant } from 'svelte-awesome-color-picker';
</script>

<ColorPicker
	components={A11yVariant}
	bind:hex
	bind:rgb
	bind:hsv
	isAlpha
	a11yColors={[
		{ textHex: '#FFF', reverse: true, placeholder: 'background' },
		{ textHex: '#FFF', bgHex: '#FF0000', reverse: true, placeholder: 'background' },
		{ bgHex: '#FFF', placeholder: 'title', size: 'large' },
		{ bgHex: '#7F7F7F', placeholder: 'button' }
	]}
/>

Note: set both attributes resverse and bgHex when you are chosing a transparency background color over a non white background.

Nullable version

The color of this example is not bound to the background since it would make other color pickers to break.

Source code

<script>
	import ColorPicker from 'svelte-awesome-color-picker';
</script>

<ColorPicker {hex} {rgb} {hsv} nullable />

right to left aligned version

Source code

<script>
	import ColorPicker from 'svelte-awesome-color-picker';
</script>

<ColorPicker {hex} {rgb} {hsv} dir="rtl" />

Always open version

Source code

<script>
	import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
</script>

<ColorPicker
	bind:rgb
	bind:hsv
	bind:hex
	components={ChromeVariant}
	sliderDirection="horizontal"
	isDialog={false}
/>

Bind event ’onInput’

In this example, the color is appended to the history at each event.

Source code

<ColorPicker
	{rgb}
	onInput={(event) => {
		historyHex = [...historyHex, event.hex];
		if (historyHex.length > 5) historyHex.shift();
	}}
/>

history variable

let history = []

Override the css variables

Source code

<ColorPicker
	bind:rgb
	bind:hsv
	bind:hex
	--picker-height="100px"
	--picker-width="100px"
	--slider-width="25px"
	--picker-indicator-size="25px"
	--picker-z-index="10"
	--input-size="100px"
	--focus-color="green"
/>

Dark theme

Source code

<script>
	import ColorPicker from 'svelte-awesome-color-picker';
</script>

<div class="dark">
	<ColorPicker />
</div>

<style>
	.dark {
		--cp-bg-color: #333;
		--cp-border-color: white;
		--cp-text-color: white;
		--cp-input-color: #555;
		--cp-button-hover-color: #777;
	}</style>

Translate the color picker

Note: the texts props can be partially overridden. It’s mostly used to translate the component. Most texts are used for accessibility aria-labels.

Source code

<ColorPicker
	bind:rgb
	bind:hsv
	bind:hex
	label="Choisir une couleur"
	texts={{
		label: {
			h: 'teinte',
			s: 'saturation',
			v: 'luminosité',
			r: 'rouge',
			g: 'vert',
			b: 'bleu',
			a: 'transparence',
			hex: 'couleur hexadécimale',
			withoutColor: 'sans couleur'
		},
		color: {
			rgb: 'rgb',
			hsv: 'hsv',
			hex: 'hex'
		},
		changeTo: 'changer Ă  '
	}}
/>

Api

The library exports 4 different things:

  • The color picker as a default export
  • ChromeVariant: the Chrome variant
  • A11yVariant: the accessibility variant (to display a panel which shows the WCAG grades)
  • HsvaColor and RgbaColor: the two types defining HSV and RGB colors

Color picker

props

nametypedefault valueusage
componentsPartial<Components>{}customize the ColorPicker component parts. Can be used to display a Chrome variant or an Accessibility Notice
labelstring'Choose a color'input label, hidden when the ColorPicker is always shown (prop isDialog={false})
namestring | undefinedundefinedinput name, useful in a native form
nullablebooleanfalseif set to true, the color picker becomes nullable (rgb, hsv and hex set to undefined)
rgbRgbaColor | nullbindable
rgb color
hsvHsvaColor | nullbindable
hsv color
hexstring | nullbindable
hex color
colorColord | nullnullbindable
Colord color
isDarkbooleanfalsebindable
indicator whether the selected color is light or dark
isAlphabooleantrueif set to false, disables the alpha channel
isDialogbooleantrueif set to false, the input and the label will not be displayed and the ColorPicker will always be visible
isOpenboolean!isDialogbindable
indicator of the popup state
position'fixed' | 'responsive' | 'responsive-x' | 'responsive-y''responsive'if set to “responsive”, the popup will adjust its x and y position depending on the available window space, “responsive-x” and “responsive-y” limit the behavior to either the x or y axis
dir'ltr' | 'rtl''ltr'directionality left to right, or right to left
isTextInputbooleantrueif set to false, hide the hex, rgb and hsv text inputs
textInputModesArray<'hex' | 'rgb' | 'hsv'>['hex', 'rgb', 'hsv']configure which hex, rgb and hsv inputs will be visible and in which order. If overridden, it is necessary to provide at least one value
sliderDirection'horizontal' | 'vertical''vertical'If set to “horizontal”, the hue and alpha sliders will be displayed horizontally. It is necessary to set this props to “horizontal” for the ChromeVariant
disableCloseClickOutsidebooleanfalseIf set to true, it will not be possible to close the color picker by clicking outside
a11yColorsArray<A11yColor>[{ bgHex: '#ffffff' }]used with the A11yVariant. Define the accessibility examples in the color picker
a11yLevel'AA' | 'AAA''AA'required WCAG contrast level
textsTextsPartial | undefinedundefinedall translation tokens used in the library; can be partially overridden; see full object type
a11yTextsA11yTextsPartial | undefinedundefinedall a11y translation tokens used in the library; override with translations if necessary; see full object type
onInput((color: { hsv: HsvaColor | null; rgb: RgbaColor | null; hex: string | null; color: Colord | null }) => void) | undefinedevent
listener, dispatch an event when the color changes

events

EventTypeUsage
input{ color, hsv, rgb, hex }Event fired on every color change (click & drag & mouse, touch)

See the example Bind event ’onInput’.

css variables

PropsDefault ValueUsage
--picker-height200pxpicker & sliders height
--picker-width200px (260px for the Chrome variant)picker width
--slider-width30pxsliders width
--picker-indicator-size10pxpicker indicator size
--picker-z-index2popup picker z-index
--input-size25pxcolor circle size
--focus-colorredfocus color
--cp-bg-colorwhitebackground color
--cp-border-colorblackborder color
--cp-text-color--cp-border-colortext color
--cp-input-color#eeebackground color of the inputs
--cp-button-hover-color#cccbackground color of the hovered button

See the example Override the css variables.

components

The color picker can be customized with components. The details and props are detailed below. It is easier to copy the library components and tweak them to your needs.

A Chrome variant and an accessibility variant are available. To use the Chrome variant you need to set the props sliderDirection to horizontal. You can also partially overwrite the components:

<script>
	import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
	import CustomInput from '$lib/path/to/my/awesome/variant/Input.svelte';
	import CustomWrapper from '$lib/path/to/my/awesome/variant/Wrapper.svelte';

	let rgb;
</script>

<!-- example with the default display and a custom Input component -->
<ColorPicker bind:rgb components={{ input: CustomInput }} />

<!-- example with the Chrome variant and a custom Wrapper component -->
<ColorPicker bind:rgb components={{ ...ChromeVariant, wrapper: CustomWrapper }} />

<!-- example with the ChromeVariant -->
<ColorPicker bind:rgb components={ChromeVariant} sliderDirection="horizontal" />

The components that can be overridden are:

The 3 components a11yNotice, a11ySummary and a11ySingleNotice are no longer included by default but can still be defined or passed through the a11yVariant object. This change was made in version 3.0.0 to lighten the library for those who do not use it.

Some components are no longer customizable in version 3.0.0: pickerWrapper, sliderWrapper, alphaWrapper, sliderIndicator and alphaIndicator. Instead you can either use the css variables or you can style them from the wrapper component.

pickerIndicator

Component representing the picker indicator.

  • The component should be positioned with position: absolute;.
  • It should also have the css property pointer-events: none;.

Props:

nametypedefault valueusage
pos{ x: number; y: number }required
indicator position in %

textInput

Component representing the rgb / hex / hsv textual input below the picker

Props:

nametypedefault valueusage
isAlphabooleanrequired
if set to false, disables the alpha channel
rgbRgbaColorrequired, bindable
rgb color
hsvHsvaColorrequired, bindable
hsv color
hexstringrequired, bindable
hex color
textInputModesArray<'hex' | 'rgb' | 'hsv'>required
configure which hex, rgb and hsv inputs will be visible and in which order. If overridden, it is necessary to provide at least one value
textsTextsrequired
all translation tokens used in the library; can be partially overridden; see full object type
onInput(color: { hsv?: HsvaColor; rgb?: RgbaColor; hex?: string }) => voidrequired, event
listener, dispatch an event when one of the color changes

Input

Component representing the button to open the color picker and a hidden input with the hex value selected by the user

Props:

nametypedefault valueusage
labelElementHTMLLabelElement | undefinedrequired, bindable
DOM element of the label wrapper
hexstring | nullrequired
hex color
labelstringrequired
input label
namestring | undefinedundefinedinput name, useful in a native form
dir'ltr' | 'rtl'required
directionality left to right, or right to left

wrapper

Encapsulates the whole color picker

Props:

nametypedefault valueusage
wrapperHTMLElement | undefinedrequired, bindable
DOM element of the wrapper element
isOpenbooleanrequired
indicator of the popup state
isDialogbooleanrequired
if set to true, the wrapper should have a dialog role and be absolute. It should be relative otherwise
childrenimport('svelte').Snippetrequired
children

nullabilityCheckbox

Displays the checkbox to toggle an undefined value

Props:

nametypedefault valueusage
isUndefinedbooleanrequired, bindable
whether the color picker is undefined
textsTextsrequired
all translation tokens used in the library; can be partially overridden; see full object type

a11yNotice

Component displaying accessible contrast issues with the color chosen.

Props:

nametypedefault valueusage
componentsComponentsrequired
customize the ColorPicker component parts. Can be used to display a Chrome variant or an Accessibility Notice
hexstringrequired
hex color
a11yColorsArray<A11yColor>required
define the accessibility examples in the color picker
a11yLevel'AA' | 'AAA'required
required WCAG contrast level
a11yTextsA11yTextsPartial | undefinedundefinedall a11y translation tokens used in the library; override with translations if necessary; see full object type

Type A11yColor:

type A11yColor = {
	placeholder?: string;
	size?: 'normal' | 'large';
} & (
	| {
			textHex: string;
			bgHex: string;
			reverse: true;
	  }
	| {
			bgHex: string;
			reverse?: false;
	  }
);

with:

AttributeTypeUsage
placeholderstringplaceholder text, default to Lorem Ipsum
sizenormal, largeused to check the contrast guidelines
reversebooleanset to true if the color picker is used to chose a background color
textHexstringwhen choosing the background color, defines the text color
bgHexstringwhen choosing the text color, defines the background color ; hen choosing th background color, defines the color behind (in case of transparency)

read more about this component accessibility in the a11y section.

a11ySingleNotice

component display the accessibility result of the color over a single item of the a11yColors props.

Props:

nametypedefault valueusage
placeholderstring | undefinedundefinedplaceholder, falls back to Lorem Ipsum
size'normal' | 'large' | undefinedundefinedsize of the text
a11yLevel'AA' | 'AAA'required
required WCAG contrast level
textColorstringrequired
placeholder text color
bgColorstringrequired
placeholder background color
contrastnumber1RGAA contrast between the text and its background. Between 1 and 21
contrastTextstringrequired
define the accessibility “contrast” text

Accessibility

The component itself

The svelte-awesome-color-picker uses svelte-awesome-slider (also made by me) to display the sliders. This library follows the W3c slider component accessibility guidelines.

The color picker follows the W3c component dialog combobox accessibility guidelines.

Accessibility notice

The component can display an accessibility notice that updates the WCAG contrast grades by using the a11yVariant component override.

The contrast between 2 colors is a value between 1 and 21. It is computed with the colord a11y plugin library based on WCAG 2.0 guidelines for contrast accessibility.

A contrast between 2 colors succeed if it follows the WCAG contrast guidelines:

Text sizeAAAAA
small text (18.5px)contrast > 4.5contrast > 7
big text (24px)contrast > 3contrast > 4.5

In the default A11ySingleNotice component that renders the AA and AAA tags, the small text values are used (can be configured for each reference color with the color props).

See and the accessibility notice variant example and the definition of the A11yColor type for more information.

How to

Fix overflow issues inside a container

If you use the ColorPicker component inside a container that is set with overflow: auto or overflow: hidden, the picker will be hidden outside of the wrapper.

To fix this, you can override the Wrapper component and use the svelte-portal library to render the picker outside of your container. An example of how to do that is presented in this svelte-awesome-color-picker portal REPL.

Fix overflow issues in the window

Please set the position props to responsive as stated in the props section.

Use the color of the document

Override the css variable --cp-border-color:

body {
	--cp-border-color: currentColor;
}

If you have a dark theme, make sure to handle it correctly.

Migration

upgrade from v3 to v4

The major version 4 have been released with a rewrite in Svelte 5. From now on, the library will only be compatible with Svelte 5. This comes with some breaking changes:

  • drop Svelte < 5 support
  • color props can be null and can no longer be undefined
  • event dispatch has been replaced with event props named on<event_name>

upgrade from v2 to v3

The major version 3 has been released to remove accessibility issues (see issue #43). The library now comes with the possibility to deselect a color and it is also possible to theme the picker for dark themes. The library has also been made simpler and lighter. This comes with some breaking changes:

  • sliderIndicator, alphaIndicator, pickerWrapper, sliderWrapper, alphaWrapper and a11ySummary were removed, you can use css variables in the wrapper component for design customization and texts in the texts and a11yTexts props instead for translating the library.
  • props isA11y has been removed. The accessibility display is now a variant: <ColorPicker components={A11yVariant} />. This change has been made to reduce the library bundle size.
  • props isInput and isPopup have been merged and renamed as isDialog.
  • props isRight has been replaced by sliderDirection="horizontal".
  • props isA11yOpen and isA11yClosable have been removed.