jQuery Colors Pickers HSL

Two color pickers have been developed upon the jQuery.colors plugin using the HSL (hue, saturation, lightness) color model.

Demonstrations

hslLite
hslCircle

Why another color picker for jQuery?

It's true, everyone seems to have their favourite one...
Well firstly I wanted to open up the functions to outside use, so that's why I made jQuery.colors.
Secondly, I was previously using the very good Farbtastic plugin, but as a user I was always confused about what to do with the middle square: it seemed to me a lot of the choices overlapped and I never really knew where to click.
Finding the Inkscape HSL picker design more intuitive, I started to make hslLite. The result is good but doesn't truly represent hue on a circle, so hslCircle was born.

Download from Github (requires jQuery 1.3.2+
-earlier versions may work too!)

Files and features

The two plugins share the following benefits over many other jQuery color pickers:

Benefits for users

  • The HSL color model is more intutive for humans than RGB (which was developed as a technical solution)
  • The pickers are designed so there's no need to really know anything about color theory
  • Each color parameter has it's own independent scale, so a user will understand easily what to adjust to get a desired result
  • What's more, the scales change according to current color, allowing the user each time to visually understand which scale does what (e.g. I want it lighter, darker, more red, more gray...)

Benefits for developers

  • Easy to adapt: completely compatible with your own styling and customisation (example below)
  • Based on jquery.colors, making color management more versatile and allows code reuse
  • Quick to load: the script includes all CSS plus minimal extra image files to load (if any) (one single HTTP request)
  • Methods easy to understand for those familiar with jQuery UI
  • No DOM overload with pixel sized divs

The individual pros of each plugin are:

jQuery.colors.pickers.hslLite.js

  • Super lightweight, one single file to load with everything you need including CSS, images and the required jQuery.colors, it comes in at 11.5kB (4.4kB gzipped). Fallback to a second file: one tiny sprite image
  • Compact design if there's little room on your page
  • Probably best for designers familiar with the layout and who understand a little about hue, saturation and lightness

jQuery.colors.pickers.hslCircle.js

  • More accurate representation of hue (in a circle), which also makes it easier to finely pick a given hue
  • Unorthodox but (hopefully) completely intuitive design: best for users with no knowledge of color theory
  • Also lightweight: if data URIs are supported, only a single css file is loaded with the images, with fallback to original sprites. (at first sight the CSS file may seem large, but when compressed with gzip it's barely larger than the original images, but for only one HTTP request instead of 3)

Dependencies: minimized and bundled files

The minimized files do not include jquery.colors.core.js nor jquery.colors.models.HSL.js, which they depend on.
The bundled files include these as well (all minimized, of course). With the bundled version you can get up and running if you don't want to customise which $.colors features to use. However, hex Strings and HTML color names are not included! (just add them if you want to)

Internet Exlporer 6 support

As transparent PNGS are used in backgrounds (for minimal bandwidth use), IE6 will fail to render properly. A fall back could be implemented by creating larger images and not placing them in the background of elements, then adding transparent PNG support for IE6.
Siding with the lack-of-support-may-force-users-to-upgrade approach as is common on the web these days, I haven't spent the time setting up this fallback, but could do if there was sufficient demand (or you could!).

Documentation

The documentation for the two plugins is identical. Here we use hslCircle for the examples.

Creating a color picker

jQueryObject.hslCircleColorPicker( [options] )

Appends a color picker to each of the matched elements with a randomly generated color. Returns jQuery.

options An object of options to apply to each color picker or a string of a setting to return in the form of a array (instead of jQuery).

More details on the options are given below, in fact applying an option on an existing color picker or whilst creating one has exactlly the same affect.
There is one exception to this: 'hsl'. If you don't set the color with the options object, then you may want to pass 'hsl' as the argument to get an array of randomly allocated hsl colors for each element.
You can only append one color picker per element, but several on one page is allowed.

$('.colorPickerWrapper').hslCircleColorPicker();
$('.colorPickerWrapper').hslCircleColorPicker('hsl');

Options

The following options can be set using the above method (examples below).
Several options can be passed at once.
Instead, if the option name is passed as a String, the function will return the value of that option for the first matched element.

hsl type : Array default : random

Represents the hsl color with the ranges [ 0..360, 0..100, 0..100]

$('.colorPickerWrapper').hslCircleColorPicker( 'hsl' );
$('.colorPickerWrapper').hslCircleColorPicker({ hsl : [ 240, 100, 50 ] });

color type : $.colors() object default : (set by hsl)

Sets or get the hsl value as the $.colors() object.

Note that when setting, if a valid type is not used, the $.colors plugin will attempt to interpret the color as an input
Furthermore, the support for unknown inputs depends on which $.colors files are included.

$('.colorPickerWrapper').hslCircleColorPicker( 'color' );
var prettyColor = $.colors('pink');
$('.colorPickerWrapper').hslCircleColorPicker({ color : prettyColor });
$('.colorPickerWrapper').hslCircleColorPicker({ color : 'rgb(255,0,0)' });

h, hue, s, saturation, l, lightness type : Float default : (set by hsl)

Represents the individual parameter of the hsl color

Note: the 'getting' of these options by passing them as a String does not work.

$('.colorPickerWrapper').hslCircleColorPicker({ h : 180, saturation:80 });

disabled type : Boolean default : false

Whether the color picker can be used or not

$('.colorPickerWrapper').hslCircleColorPicker( 'disabled' );
$('.colorPickerWrapper').hslCircleColorPicker({ disabled : true });

onStartChange, onChange, onEndChange type : Function default : null

Events that are triggered when the user 1) clicks on the color picker, 2) drags the color picker and 3) releases the mouse.

Each function is passed the $.colors() object

$('.colorPickerWrapper').hslCircleColorPicker({ onEndChange : function( color ){
  alert( color.toString() );
} });

Global setting

$.colors.pickers.hslCircle.pathToImages type : String default : matches the folder where the script file is kept

Where the images are kept (if a browser doesn't support data URIs and the fallback is used)

$.colors.pickers.hslCircle.pathToImages = 'path/to/images/';

Customisation (with example)

The two plugins can be easily customised for users. The plugin attempts to insert the CSS before any other styles in the head, so that your styling will override the defaults.

If you make something more advanced, you could even share it as a new plugin!

HTML outlines

hslLiteColorPicker

<div class="hslLiteColorPicker">
  <div class="scale h"></div>
  <div class="scale s"></div>
  <div class="scale l"></div>
</div>

The widths are fixed at 200px.

hslCircleColorPicker

<div class="hslCircleColorPicker">
  <div class="scale h"></div>
  <div class="scale s"></div>
  <div class="scale l"></div>
</div>

The inner divs are absolutely positioned within the relative wrapper.

Each scale contains the following markup for the handles:

<span class='handle'>
  <span></span>
  <span class='outline'></span>
</span>

Custom example

So we can now do anything, such as this:

with the following code

// append a picker wrapper to the body
$('#customisedPickersExample').append( $('<div/>').attr('id','customisedLitePicker').css('visibility','hidden') );

// insert the picker
$('#customisedLitePicker').hslLiteColorPicker({
  // set the original color to the left border
  onStartChange : function(color){
    $('#customisedLitePicker>.hslLiteColorPicker').css('border-left-color', color.toString() );
  },
  onChange : function(color){
    // set the new color to the right border
    $('#customisedLitePicker>.hslLiteColorPicker').css('border-right-color', color.toString() );

    updateInputFormColors( color );

  },
  // remove the border colors
  onEndChange : function(color){
    $('#customisedLitePicker>.hslLiteColorPicker').css('border-color', 'transparent' );
  },
  l:75
}).hide().css('visibility','');

// add hover titles and insert text before each scale
$('#customisedLitePicker .h').before( $('<p/>').text('1. Choose a colour') )
  .attr('title','[ hue ]');
$('#customisedLitePicker .s').before( $('#customisedLitePicker .l') ); // swap the lightness with the saturation scale
$('#customisedLitePicker .l').before( $('<p/>').text('2. How light (or dark)?') )
  .attr('title','[ lightness ]');
$('#customisedLitePicker .s').before( $('<p/>').text('3. How much colour? (none = black+white)') )
  .attr('title','[ saturation ]');


// initiate the input color with the random one made by the color picker
updateInputFormColors( $('#customisedLitePicker').hslLiteColorPicker('color') );

// show/hide the color picker
$('#customisedPickersExample').bind('mouseleave',function(){
  $('#customisedLitePicker').slideUp();
}).children('input').bind('focus click',function(){
  $('#customisedLitePicker').slideDown();
}).keyup(function(){
  // try to update the color with the current text
  try{
    var newColor = $.colors( this.value );
    $('#customisedLitePicker').hslLiteColorPicker({ color:newColor });
    updateInputFormColors(newColor);
  }catch(e){}
});


// update the input form (and set font color to opposing lightness so that it's visible)
function updateInputFormColors( color ){

  var textColor = $.colors( color.get() );
  textColor.model('HSL').set('s',0).set('l', 100 - Math.round( textColor.get('l') /100)*100);
  $('#customisedPickersExample>input')
    .css('background-color', color.toString() )
    .val( color.toString('hex') )
    .css('color', textColor.toString() );
}
#customisedPickersExample>input{
  width:200px;
  display:inline-block;
}
#customisedLitePicker>.hslLiteColorPicker{
  border:0 solid transparent;
  border-width:0 1em;
  padding:1em;
  background-color:white;
  color:black;
}
#customisedLitePicker>.hslLiteColorPicker>.scale{
  font-size:2em;
  cursor:col-resize;
}
#customisedLitePicker .handle>.outline{
  display:none;
}
#customisedLitePicker .scale:hover>.handle>.outline{
  display:inline;
}

◂ Back to the code section