HSL Color Picker

A color picker in HSL color space.

Lightness has a median value of 50 which shows full color, while 100 lightness is white, and 0 lightness is black, regardless of hue or saturation.

HSL color space can be used in both p5.js and CSS.

Source Code for this Sketch

// How tall the color picker should be
const scale = 360
const degScale = scale/360
const centScale = scale/100
const header = document.getElementById("main-nav-wrapper")

// Initialize color values
let hue = 91/360*scale
let lightness = 51
let saturation = 61

function setup() {
	createCanvas(420, scale+170, P2D, canvas)
	colorMode(HSL)
	noStroke()
	describe("A color picker for hue, saturation, lightness")
}

// normalize converts a scaled input value to a normalized
// value based on the scale factor.
function normalize(input, factor) {
	return Math.round(input/factor)
}

// inRect checks whether the mouse's current position is
// inside the given rectangle (x, y) marks the top left
// corner, (w, h) are height and width measured to the
// right and downward
function inRect(x, y, w, h) {
	return (mouseX >= x && mouseX < x+w && mouseY >= y && mouseY < y+h)
}

// toCSS formats hsl values for use in CSS rules
function toCSS(hue, saturation, lightness) {
	return `hsl(${round(hue)}deg ${round(saturation)}% ${round(lightness)}%)`
}

// toP5JS formats hsl values for use in p5.js scripts
function toP5JS(hue, saturation, lightness) {
	return `colorMode(HSL); color(${round(hue)}, ${round(saturation)}, ${round(lightness)})`
}

// label shows hsl values in css and p5.js formats
function label(hue, saturation, lightness) {
	// raw:  h=${hue}, s=${saturation}, l=${lightness}
	return `css:  ${toCSS(hue, saturation, lightness)}
p5js: ${toP5JS(hue, saturation, lightness)}`
}

// pointer creates a triangle pointing to a spot indicated by
// x, y. Normally the triangle "points" from left to right. If
// rtl is true, it will point from right to left instead.
function pointer(x, y, rtl) {
	fill(25)
	if(rtl) {
		triangle(x, y, x+6, y-3, x+6, y+3)
	} else {
		triangle(x, y, x-6, y-3, x-6, y+3)
	}
}

function draw() {
	background(90)

	// Hue selector
	for(let i = 0; i < scale; i++) {
		fill(i, saturation, lightness)
		rect(10, i+10, 100, 1)
	}
	if(mouseIsPressed && inRect(10, 10, 100, scale)) {
		hue = normalize(mouseY-10, degScale)
	}
	pointer(10, hue*degScale+10)
	pointer(110, hue*degScale+10, true)

	// Saturation Selector
	for(let i = 0; i < scale; i++) {
		fill(hue, 100*((scale-i)/scale), lightness)
		rect(160, i+10, 100, 1)
	}
	if (mouseIsPressed && inRect(160, 10, 100, scale)) {
		saturation = normalize(scale-(mouseY-10), centScale)
	}
	pointer(160, scale-saturation*centScale+10)
	pointer(260, scale-saturation*centScale+10, true)
	
	// Lightness selector
	for(let i = 0; i < scale; i++) {
		fill(hue, saturation, 100*((scale-i)/scale))
		rect(310, i+10, 100, 1)
	}
	if (mouseIsPressed && inRect(310, 10, 100, scale)) {
		lightness = normalize(scale-(mouseY-10), centScale)
	}
	pointer(310, scale-lightness*centScale+10)
	pointer(410, scale-lightness*centScale+10, true)

	// Draw a color sample
	fill(hue, saturation, lightness)
	rect(10, scale+60, 400, 100)

	// Label numeric data for the color we are showing
	fill(90)
	rect(60, scale+90, 300, 40)
	fill(0)
	text(label(hue, saturation, lightness), 70, scale+105)
	header.style.backgroundColor = toCSS(hue, saturation, lightness)
}

You may use all or part of the p5 code seen on this page for your own creations, without restriction. Attribution is appreciated but not required.

This sketch also includes the following sources: p5common.js . Sources are available under their respective licenses.

See all p5.js sketches