<hue-wheel>

<hue-wheel>

A polar color wheel: hue around the circle, and (optionally) a second channel along the radius. Works in any polar color space: nothing is hardcoded, everything is derived from the space’s metadata.

Basic use (just hue, rendered as a ring):

<hue-wheel space="oklch"></hue-wheel>

Add a radial axis with channel (here, chroma) and a starting color:

<hue-wheel space="oklch" channel="c" color="oklch(0.7 0.15 200)"></hue-wheel>

Any polar space works:

<hue-wheel space="hsl" channel="s" color="hsl(200 80% 50%)"></hue-wheel>

Click or drag to set the color (or to add one if none is present); once the marker is focused, arrow keys nudge it (←→ hue, ↑↓ channel). Use readonly to display without editing:

<hue-wheel space="lch" channel="c" color="lch(60 50 120)" readonly></hue-wheel>

Extra points

Slot <color-swatch> or <color-scale> elements to plot additional (non-editable) points, positioned by their own hue and channel. Hovering a point reveals its details as a tooltip.

<hue-wheel space="oklch" channel="c" color="oklch(0.7 0.15 200)">
	<color-scale space="oklch"
		colors="oklch(0.6 0.2 20), oklch(0.7 0.25 140), oklch(0.5 0.18 300)"></color-scale>
	<color-swatch>oklch(0.8 0.1 90)</color-swatch>
</hue-wheel>

Custom marker

By default the current color is shown as a plain dot with no tooltip. To customize it, slot your own <color-swatch slot="marker"> — hue-wheel keeps its color in sync, positions it, and makes it the slider, while you control its looks (and can re-enable a details tooltip via info + --details-style: compact):

<hue-wheel space="oklch" channel="c" color="oklch(0.7 0.15 200)">
	<color-swatch slot="marker" info="oklch.h, oklch.c"
		style="--dot-size: 1.4em; --dot-border: 3px solid black; --details-style: compact"></color-swatch>
</hue-wheel>

Building a basic custom color picker

A <hue-wheel> covers two of a color’s three coordinates: hue (the angle) and one radial channel (here, chroma). Pair it with a <channel-slider> for the remaining channel (lightness) and a <space-picker> to switch polar spaces, and you have a full color picker. A <color-swatch> shows the result.

The wheel owns hue + chroma, the slider owns lightness, and the space picker switches the whole thing into another polar space (we list the polar spaces that have a lightness channel, since the slider is fixed to l). The wheel’s radial channel is whatever’s left over — the non-hue, non-lightness coordinate, so it’s chroma in oklch/lch and saturation in hsl/okhsl. Each control mirrors its color to the others (and the swatch) on input:

<div class="wheel-picker">
	<label>
		Space:
		<space-picker id="cp_space" spaces="oklch, okhsl, lch, hsl" value="oklch"
			oninput="let s = this.selectedSpace; cp_wheel.space = cp_lightness.space = s; cp_wheel.channel = Object.keys(s.coords).find(c => c !== 'l' && s.coords[c].type !== 'angle')"></space-picker>
	</label>

	<hue-wheel id="cp_wheel" space="oklch" channel="c" color="oklch(0.7 0.18 200)"
		oninput="cp_lightness.color = cp_out.color = this.color"></hue-wheel>

	<channel-slider id="cp_lightness" space="oklch" channel="l" color="oklch(0.7 0.18 200)"
		oninput="cp_wheel.color = cp_out.color = this.color">Lightness</channel-slider>

	<color-swatch id="cp_out" size="large">oklch(0.7 0.18 200)</color-swatch>
</div>

<style>
	.wheel-picker {
		display: flex;
		flex-flow: column;
		align-items: center;
		gap: 1em;

		channel-slider {
			align-self: stretch;
		}
	}
</style>

Keyboard

Focus the marker (with Tab) to adjust the color with the keyboard:

A readonly wheel’s marker stays focusable (so its value is exposed to assistive tech) but can’t be changed. The radial channel isn’t yet a separate slider for assistive tech; its value is announced as part of the marker’s value text.

Notes

Reference

Slots

Name Description
(default) Overlay content rendered on top of the wheel (used to build <gamut-wheel>). Slotted <color-swatch> / <color-scale> elements are also plotted as extra points.
marker The draggable marker for the current color. Defaults to a built-in dot; slot your own <color-swatch slot="marker"> to fully control its appearance (and, e.g., add a details tooltip). hue-wheel sets its color, positions it, and makes it the slider.

Attributes & Properties

Attribute Property Property type Default value Description
space spaceId / space string / ColorSpace oklch The polar color space of the wheel. The attribute and the space property accept a space id or ColorSpace; the spaceId property is always the id string. A non-polar value is rejected (the space setter throws; a non-polar attribute is ignored with a warning).
channel channel string | null null Coordinate shown on the radial axis. When omitted, the wheel shows only hue (as a ring).
color color Color | null null The current color (always in space). null when no color is set.
- hueValue number - The current hue value. Read/write.
- channelValue number | undefined - The current channel value, if channel is set. Read/write.
readonly readonly boolean false When set, the color cannot be added or edited.

Events

Name Description
input Fired continuously while the color is being changed (drag, click, arrow keys).
change Fired when a change is committed (pointer release, or each arrow keypress).
colorchange Fired whenever the color property changes, for any reason.

CSS variables

Variable Type Description
--size <length> The diameter of the wheel. Defaults to 320px.
--ring-thickness <number> In ring mode (no channel), the ring’s thickness as a fraction of the radius. Defaults to 0.35.
--dot-size <length> The diameter of the plotted points (passed through to their <color-swatch> dots). Defaults to 1em.

Parts

Name Description
wheel The circular wheel container.
disc The painted hue/channel field.
marker The draggable marker showing the current color.

Installation

To install all color elements, check out the instructions on the homepage. The rest of this section is about using only <hue-wheel>.

If you’re using a bundler, or an import map manager like Nudeps or JSPM, you can import it via a bare specifier:

import "color-elements/hue-wheel";

or:

import { HueWheel } from "color-elements";

Otherwise, you can use a CDN such as esm.sh:

<script src="https://esm.sh/color-elements/hue-wheel" type="module"></script>