What is @simonwep/pickr?
@simonwep/pickr is a highly customizable color picker library for JavaScript. It allows users to select colors in various formats (HEX, RGB, HSV, etc.) and provides a user-friendly interface with multiple themes and options for integration into web applications.
What are @simonwep/pickr's main functionalities?
Basic Color Picker
This code initializes a basic color picker with a classic theme and a set of predefined swatches. It also enables various color formats and interaction options.
const pickr = Pickr.create({
el: '.color-picker',
theme: 'classic',
swatches: [
'rgba(244, 67, 54, 1)',
'rgba(233, 30, 99, 0.95)',
'rgba(156, 39, 176, 0.9)',
'rgba(103, 58, 183, 0.85)',
'rgba(63, 81, 181, 0.8)',
'rgba(33, 150, 243, 0.75)',
'rgba(3, 169, 244, 0.7)',
'rgba(0, 188, 212, 0.7)',
'rgba(0, 150, 136, 0.75)',
'rgba(76, 175, 80, 0.8)',
'rgba(139, 195, 74, 0.85)',
'rgba(205, 220, 57, 0.9)',
'rgba(255, 235, 59, 0.95)',
'rgba(255, 193, 7, 1)'
],
components: {
preview: true,
opacity: true,
hue: true,
interaction: {
hex: true,
rgba: true,
hsla: true,
hsva: true,
cmyk: true,
input: true,
clear: true,
save: true
}
}
});
Inline Color Picker
This code initializes an inline color picker with a monolith theme. The picker is displayed inline rather than as a popup, making it suitable for embedding directly within a page layout.
const pickr = Pickr.create({
el: '.color-picker',
theme: 'monolith',
inline: true,
components: {
preview: true,
opacity: true,
hue: true,
interaction: {
hex: true,
rgba: true,
hsla: true,
hsva: true,
cmyk: true,
input: true,
clear: true,
save: true
}
}
});
Color Picker with Custom Events
This code initializes a color picker with a nano theme and sets up a custom event listener for the 'save' event. When a color is saved, it logs the selected color in RGBA format to the console.
const pickr = Pickr.create({
el: '.color-picker',
theme: 'nano',
components: {
preview: true,
opacity: true,
hue: true,
interaction: {
hex: true,
rgba: true,
hsla: true,
hsva: true,
cmyk: true,
input: true,
clear: true,
save: true
}
}
});
pickr.on('save', (color, instance) => {
console.log('Color saved:', color.toRGBA().toString());
});
Other packages similar to @simonwep/pickr
react-color
react-color is a collection of color pickers for React applications. It offers a variety of color picker components, such as Sketch, Photoshop, Chrome, and more. Compared to @simonwep/pickr, react-color is specifically designed for React and provides a more extensive set of pre-built color picker styles.
vanilla-picker
vanilla-picker is a lightweight, zero-dependency color picker library for vanilla JavaScript. It provides a simple and straightforward API for creating color pickers. While it lacks some of the advanced customization options of @simonwep/pickr, it is a good choice for projects that require a minimal and easy-to-use color picker.
Flat, Simple, Hackable Color-Picker.
Features
- 🎨 Themes
- 🔄 Simple usage
- 🚫 Zero dependencies
- 🌈 Multiple color representations
- 🔍 Color comparison
- 🎚️ Opacity control
- 🖱️ Detail adjustments via mouse-wheel
- 📱 Responsive and auto-positioning
- 👆 Supports touch devices
- 🎨 Swatches for quick-selection
- ♿ Fully accessible and i18n
- 🌑 Shadow-dom support
Status of this project
[!IMPORTANT]
This project might continue to get important security- and bug-related updates but its feature set is frozen, and it's highly unlikely that it'll get new features or enhancements.
The reason behind this decision is the way this tool has been build (monolithic, the core is one single file, everything is in plain JS etc.) which makes it incredible hard to maintain, tests become impossible at this stage without a complete rewrite, and the fun is gone at such a level of cramped complexity.
Personally I recommend building these UI-Related "widgets" directly into the app with the framework you're using which takes more time but in return gives you full power of how it should work and look like. Frameworks such as (p)react, vue and svelte will make it a breeze to develop such things within a day.
Themes
Nano uses css-grid thus it won't work in older browsers.
Getting Started
Node
Note: The readme is always up-to-date with the latest commit. See Releases for installation instructions regarding to the latest version.
Install via npm:
$ npm install @simonwep/pickr
Install via yarn:
$ yarn add @simonwep/pickr
Include code and style:
import '@simonwep/pickr/dist/themes/classic.min.css';
import '@simonwep/pickr/dist/themes/monolith.min.css';
import '@simonwep/pickr/dist/themes/nano.min.css';
import Pickr from '@simonwep/pickr';
import Pickr from '@simonwep/pickr/dist/pickr.es5.min';
Attention: The es5-bundle (e.g. legacy version) is quite big (around a triple of the modern bundle).
Please take into consideration to use the modern version and add polyfills later to your final bundle!
(Or better: give a hint to users that they should use the latest browsers).
Browsers such as IE are not supported (at least not officially).
Browser
jsdelivr:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/classic.min.css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/monolith.min.css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/nano.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/pickr.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/pickr.es5.min.js"></script>
Be sure to load the pickr.min.js
(or the es5 version) after pickr.min.css
. Moreover the script
tag doesn't work with the defer
attribute.
Usage
const pickr = Pickr.create({
el: '.color-picker',
theme: 'classic',
swatches: [
'rgba(244, 67, 54, 1)',
'rgba(233, 30, 99, 0.95)',
'rgba(156, 39, 176, 0.9)',
'rgba(103, 58, 183, 0.85)',
'rgba(63, 81, 181, 0.8)',
'rgba(33, 150, 243, 0.75)',
'rgba(3, 169, 244, 0.7)',
'rgba(0, 188, 212, 0.7)',
'rgba(0, 150, 136, 0.75)',
'rgba(76, 175, 80, 0.8)',
'rgba(139, 195, 74, 0.85)',
'rgba(205, 220, 57, 0.9)',
'rgba(255, 235, 59, 0.95)',
'rgba(255, 193, 7, 1)'
],
components: {
preview: true,
opacity: true,
hue: true,
interaction: {
hex: true,
rgba: true,
hsla: true,
hsva: true,
cmyk: true,
input: true,
clear: true,
save: true
}
}
});
You can find more examples here.
Events
Since version 0.4.x
Pickr is event-driven. Use the on(event, cb)
and off(event, cb)
functions to bind / unbind eventlistener.
Event | Description | Arguments |
---|
init | Initialization done - pickr can be used | PickrInstance |
hide | Pickr got closed | PickrInstance |
show | Pickr got opened | HSVaColorObject, PickrInstance |
save | User clicked the save / clear button. Also fired on clear with null as color. | HSVaColorObject or null, PickrInstance |
clear | User cleared the color. | PickrInstance |
change | Color has changed (but not saved). Also fired on swatchselect | HSVaColorObject, eventSource, PickrInstance |
changestop | User stopped to change the color | eventSource, PickrInstance |
cancel | User clicked the cancel button (return to previous color). | PickrInstance |
swatchselect | User clicked one of the swatches | HSVaColorObject, PickrInstance |
Example:
pickr.on('init', instance => {
console.log('Event: "init"', instance);
}).on('hide', instance => {
console.log('Event: "hide"', instance);
}).on('show', (color, instance) => {
console.log('Event: "show"', color, instance);
}).on('save', (color, instance) => {
console.log('Event: "save"', color, instance);
}).on('clear', instance => {
console.log('Event: "clear"', instance);
}).on('change', (color, source, instance) => {
console.log('Event: "change"', color, source, instance);
}).on('changestop', (source, instance) => {
console.log('Event: "changestop"', source, instance);
}).on('cancel', instance => {
console.log('Event: "cancel"', instance);
}).on('swatchselect', (color, instance) => {
console.log('Event: "swatchselect"', color, instance);
});
Where source
can be
slider
- Any slider in the UI.input
- The user input field.swatch
- One of the swatches.
Options
const pickr = new Pickr({
el: '.color-picker',
container: 'body',
theme: 'classic',
closeOnScroll: false,
appClass: 'custom-class',
useAsButton: false,
padding: 8,
inline: false,
autoReposition: true,
sliders: 'v',
disabled: false,
lockOpacity: false,
outputPrecision: 0,
comparison: true,
default: '#42445a',
swatches: null,
defaultRepresentation: 'HEX',
showAlways: false,
closeWithKey: 'Escape',
position: 'bottom-middle',
adjustableNumbers: true,
components: {
palette: true,
preview: true,
opacity: true,
hue: true,
interaction: {
hex: false,
rgba: false,
hsla: false,
hsva: false,
cmyk: false,
input: false,
cancel: false,
clear: false,
save: false,
},
},
i18n: {
'ui:dialog': 'color picker dialog',
'btn:toggle': 'toggle color picker dialog',
'btn:swatch': 'color swatch',
'btn:last-color': 'use previous color',
'btn:save': 'Save',
'btn:cancel': 'Cancel',
'btn:clear': 'Clear',
'aria:btn:save': 'save and close',
'aria:btn:cancel': 'cancel and close',
'aria:btn:clear': 'clear and close',
'aria:input': 'color input field',
'aria:palette': 'color selection area',
'aria:hue': 'hue selection slider',
'aria:opacity': 'selection slider'
}
});
Selection through a Shadow-DOM
Example setup:
<div class="entry">
#shadow-root
<div class="innr">
<div class="another">
#shadow-root
<div class="pickr"></div>
</div>
</div>
</div>
To select the .pickr
element you can use the custom >>
shadow-dom-selector in el
:
el: '.entry >> .innr .another >> .pickr'
Every ShadowRoot
of the query-result behind a >>
gets used in the next query selection.
An alternative would be to provide the target-element itself as el
.
The HSVaColor object
As default color representation is hsva (hue
, saturation
, value
and alpha
) used, but you can also convert it to other formats as listed below.
- hsva.toHSVA() - Converts the object to a hsva array.
- hsva.toHSLA() - Converts the object to a hsla array.
- hsva.toRGBA() - Converts the object to a rgba array.
- hsva.toHEXA() - Converts the object to a hexa-decimal array.
- hsva.toCMYK() - Converts the object to a cmyk array.
- hsva.clone() - Clones the color object.
The toString()
is overridden, so you can get a color representation string.
hsva.toRGBA();
hsva.toRGBA().toString();
hsva.toRGBA().toString(3);
Methods
- pickr.setHSVA(h
:Number
,s:Number
,v:Number
,a:Float
, silent:Boolean
) - Set an color, returns true if the color has been accepted. - pickr.setColor(str:
:String | null
, silent:Boolean
):Boolean
- Parses a string which represents a color (e.g. #fff
, rgb(10, 156, 23)
) or name e.g. 'magenta', returns true if the color has been accepted. null
will clear the color.
If silent
is true (Default is false), the button won't change the current color.
- pickr.on(event
:String
, cb:Function
):Pickr
- Appends an event listener to the given corresponding event-name (see section Events). - pickr.off(event
:String
, cb:Function
):Pickr
- Removes an event listener from the given corresponding event-name (see section Events). - pickr.show()
:Pickr
- Shows the color-picker. - pickr.hide()
:Pickr
- Hides the color-picker. - pickr.disable()
:Pickr
- Disables pickr and adds the disabled
class to the button. - pickr.enable()
:Pickr
- Enables pickr and removes the disabled
class from the button. - pickr.isOpen()
:Pickr
- Returns true if the color picker is currently open. - pickr.getRoot()
:Object
- Returns the dom-tree of pickr as tree-structure. - pickr.getColor()
:HSVaColor
- Returns the current HSVaColor object. - pickr.getSelectedColor()
:HSVaColor
- Returns the currently applied color. - pickr.destroy() - Destroys all functionality.
- pickr.destroyAndRemove() - Destroys all functionality and removes the pickr element including the button.
- pickr.setColorRepresentation(type
:String
):Boolean
- Change the current color-representation. Valid options are HEX
, RGBA
, HSVA
, HSLA
and CMYK
, returns false if type was invalid. - pickr.getColorRepresentation()
:String
- Returns the currently used color-representation (eg. HEXA
, RGBA
...) - pickr.applyColor(silent
:Boolean
):Pickr
- Same as pressing the save button. If silent is true the onSave
event won't be called. - pickr.addSwatch(color
:String
):Boolean
- Adds a color to the swatch palette. Returns true
if the color has been successful added to the palette. - pickr.removeSwatch(index
:Number
):Boolean
- Removes a color from the swatch palette by its index, returns true if successful.
Static methods
Pickr
- create(options
:Object
):Pickr
- Creates a new instance.
Pickr.utils
- once(element
:HTMLElement
, event:String
, fn:Function
[, options :Object
]) - Attach an event handle which will be fired only once - on(elements
:HTMLElement(s)
, events:String(s)
, fn:Function
[, options :Object
]) - Attach an event handler function. - off(elements
:HTMLElement(s)
, event:String(s)
, fn:Function
[, options :Object
]) - Remove an event handler. - createElementFromString(html
:String
):HTMLElement
- Creates an new HTML Element out of this string. - eventPath(evt
:Event
):[HTMLElement]
- A polyfill for the event-path event propery. - createFromTemplate(str
:String
) - See inline doumentation. - resolveElement(val
:String|HTMLElement
) - Resolves a HTMLElement
, supports >>>
as shadow dom selector. - adjustableInputNumbers(el
:InputElement
, mapper:Function
) - Creates the possibility to change the numbers in an inputfield via mouse scrolling.
The mapper function takes three arguments: the matched number, an multiplier and the index of the match.
Use this utils carefully, it's not for sure that they will stay forever!
Static properties
- version - The current version.
- I18N_DEFAULTS - i18n default values.
- DEFAULT_OPTIONS - Default options (Do not override this property itself, only change properties of it!).
FAQ
How do I initialize multiple pickr's? Can I access the instance via class
or id
?
No, you can't. You need to keep track of your instance variables - pickr is (not yet) a web-component.
The best option would be to create new elements via document.createElement
and directly pass it as el
.
example.
I want to use pickr in a form, how can I do that?
You can use useAsButton: true
and pass a reference (or selector) of your input-element as el
. Then you can update the input-element whenever a change was made. example.
I want to update options after mounting pickr, is that possible?
Unfortunately not. The core-code of this project is rather old (over 2 years), and I made it in my early js-days - the widget is not able to dynamically re-render itself in that way.
You have to destroy and re-initialize it.
Contributing
If you want to open a issue, create a Pull Request or simply want to know how you can run it on your local machine, please read the Contributing guide.