Skip to content

Color Picker

Allows users to select a color through various interfaces like spectrum, swatches, or input.

  • Color Chooser
  • Color Selector

Overview

The Color Picker allows users to select a color value through one or more interfaces: a two-dimensional spectrum/gradient area, hue and saturation sliders, alpha (opacity) controls, predefined swatches, or direct text input for hex/RGB/HSL values.

Color pickers range from simple (a grid of preset swatches) to highly complex (full spectrum with multiple color model inputs, eyedropper tool, and color harmony suggestions). The appropriate complexity depends entirely on the user's task and expertise level.

For most applications — themes, branding, tag colors — a curated swatch palette is sufficient. Full-spectrum pickers are necessary when users need precise color control: design tools, data visualization configuration, CSS editing, or brand guideline enforcement.

The color picker is inherently visual, which creates significant accessibility challenges. Color selection by definition relies on seeing color, but the component itself must still be keyboard-navigable, screen-reader-operable, and usable by people with color vision deficiency. The text input fallback (hex/RGB values) is essential for accessibility.

When to use a Color Picker:

  • Theme or brand customization (background color, accent color, text color)
  • Data visualization configuration (chart colors, category colors)
  • Content creation tools (text editors, design tools, drawing apps)
  • Tag, label, or category color assignment
  • CSS property editing in developer tools

When NOT to use a Color Picker:

  • Predefined semantic choices (status: success/warning/error) — use a Select with color swatches
  • Binary choices — use a Switch or Radio Button
  • When color accuracy is critical for physical output (print, manufacturing) — use professional color management tools

Our Color Palette Generator tool is the ideal companion for color picker implementations. It generates harmonious palettes, shows accessibility contrast ratios, and exports color values in multiple formats. Pair it with the Contrast Checker to ensure any user-selected colors meet WCAG requirements when used for text or UI elements.

Variants

Interaction Variants

VariantDescriptionComplexityUse Case
Swatches OnlyGrid of predefined color options. Click to select.LowTag colors, category labels, simple theming
Spectrum + Hue2D saturation/brightness gradient with a hue slider bar. The classic "color picker."MediumDesign tools, theme editors, CSS customization
Spectrum + Hue + AlphaFull spectrum with an additional opacity/transparency slider.Medium–HighDesign tools with transparency support
Input OnlyText field accepting hex, RGB, or HSL values. No visual picker.LowDeveloper tools, quick entry for users who know color values
Compact TriggerA small color swatch button that opens a popover with the full picker.VariesForm fields, settings panels, inline editors
EyedropperUses the browser's EyeDropper API to sample a color from anywhere on screen.Low (interaction)Design tools, browser-native color sampling
Full PanelCombines spectrum, sliders, swatches, text inputs, eyedropper, and color harmony suggestions.HighProfessional design software

Color Model Variants

ModelFormatBest For
Hex#FF5733, #F57Web development — the universal web color format
RGBrgb(255, 87, 51)Web development, screen-based design
RGBArgba(255, 87, 51, 0.8)Colors with transparency
HSLhsl(14, 100%, 60%)Intuitive for humans — hue rotation + saturation + lightness
HSLAhsla(14, 100%, 60%, 0.8)HSL with transparency
HSB/HSVhsb(14, 80%, 100%)Design tools (Figma, Photoshop use HSB internally)
OKLCHoklch(70% 0.15 50)Modern CSS — perceptually uniform lightness

Size Variants

SizeSpectrum AreaUse Case
Compact160×160pxPopovers, inline form fields
Default220×220pxSettings panels, standalone pickers
Large280×280px+Professional tools, dedicated color pages

Users who work in the Color Palette Generator tool are already familiar with the spectrum + hue pattern — maintain consistency by using the same interaction model in your picker.

Properties

Color Picker Properties

PropertyTypeDefaultDescription
valuestring—Current color value (hex string, e.g., "#FF5733")
defaultValuestring"#000000"Initial color (uncontrolled)
onChange(color: string) => void—Fired on every color change (during drag, typing, swatch click)
onChangeEnd(color: string) => void—Fired when interaction ends (mouseup on spectrum, blur on input). Use for expensive operations.
format'hex' | 'rgb' | 'hsl''hex'Output format of the color value
alphabooleanfalseEnable alpha/opacity channel
swatchesstring[]—Array of preset color values to display as a swatch grid
showInputbooleantrueShow hex/RGB/HSL text input fields
showSpectrumbooleantrueShow the 2D gradient spectrum
showEyeDropperbooleanfalseShow eyedropper button (requires EyeDropper API support)
disabledbooleanfalseDisables the picker
labelstring—Accessible label for the color picker
previewSize'sm' | 'md' | 'lg''md'Size of the color preview swatch trigger
popoverbooleantrueRender picker in a popover vs. inline
returnAlphabooleanfalseInclude alpha in output (#FF573380 or rgba())

Color Output Helpers

Most implementations provide utility methods:

  • toHex() → "#FF5733"
  • toRgb() → { r: 255, g: 87, b: 51 }
  • toHsl() → { h: 14, s: 100, l: 60 }
  • toRgbString() → "rgb(255, 87, 51)"
  • toHslString() → "hsl(14, 100%, 60%)"

Token Mappings

Design Token Mappings

Token CategoryToken ExampleColor Picker Usage
Color – Border--color-neutral-300Input field and swatch border
Color – Background--color-whitePicker panel and input background
Color – Text--color-neutral-900Input text and labels
Color – Focus--color-focus-ringFocus indicator on inputs, swatches, and spectrum
Spacing – Padding--space-3 (12px)Panel internal padding
Spacing – Gap--space-2 (8px)Gap between swatches, between sections
Spacing – Swatch Size24px × 24pxIndividual swatch clickable area
Border Radius--radius-md (8px)Panel corners, input corners
Border Radius – Swatch--radius-sm (4px) or 50%Individual swatch shape (square or circular)
Shadow--shadow-lgPopover elevation
Z-Index--z-popover (40)Popover layering
CursorcrosshairOver the spectrum gradient area
Transition--duration-fast (150ms)Swatch hover, input focus transitions

The color picker is unique in that its primary content IS color — the spectrum gradient, hue bar, and alpha slider are rendered dynamically using CSS gradients or canvas, not design tokens. Tokens apply to the structural chrome (borders, backgrounds, spacing) around the color content.

For generating the swatch palette values to pass to the swatches prop, use the Color Palette Generator.

States

Interactive States

StateVisual TreatmentBehavior
Rest (Trigger)Color swatch showing current value, possibly with a border. Chevron or edit icon.Click to open the picker popover.
OpenPopover with spectrum, sliders, swatches, and input fields visible.User can interact with all sub-controls.
Spectrum DraggingCrosshair cursor, small circle indicator follows the pointer across the 2D gradient.Hue comes from the hue slider; saturation and brightness from X/Y position.
Hue Slider DraggingThumb moves along the rainbow gradient bar. Spectrum updates in real time.Changes the hue of the entire spectrum.
Alpha Slider DraggingThumb on a transparency gradient (checkerboard → color).Adjusts opacity from 0% to 100%.
Swatch HoverScale up slightly (transform: scale(1.15)) with shadow.Indicates clickability.
Swatch SelectedCheckmark overlay or ring/border highlight.Shows which preset is active.
Input FocusStandard text input focus state — primary border, focus ring.User is typing a color value directly.
Input InvalidRed border, error text.Typed value is not a valid color (e.g., "#GGHHII").
Eyedropper ActiveNative OS eyedropper UI (browser-controlled).User is sampling a color from the screen.
DisabledMuted trigger swatch, no interaction.Picker cannot be opened.

Spectrum Interaction Details

The spectrum area is a 2D gradient:

  • X-axis: Saturation (left = desaturated/gray, right = fully saturated)
  • Y-axis: Brightness/Value (top = bright, bottom = dark/black)
  • The hue slider determines the dominant hue visible in the spectrum.

The position indicator (small circle) should:

  • Have a white border with a dark inner border for visibility on all backgrounds.
  • Update its position when the color value changes from outside (controlled mode).
  • Support both mouse/touch dragging and keyboard arrow key nudging.

Accessibility

Accessibility Requirements

Color pickers are inherently visual components, but they must remain operable for all users. The key principle: every color selection possible with a mouse must also be achievable via keyboard and expressible in text.

Label Association (WCAG 1.3.1, 4.1.2):

  • The picker trigger (swatch button) must have an accessible name: aria-label="Select background color" or an associated <label>.
  • Display the current color value as text (hex code) near the swatch so it's not conveyed by color alone (WCAG 1.4.1 Use of Color).
  • Each sub-control (spectrum, hue slider, alpha slider, input field) needs its own accessible label.

Keyboard Interaction (WCAG 2.1.1 Keyboard):

  • Trigger: Enter / Space opens the popover.
  • Spectrum area: role="slider" or role="application" with arrow keys moving the indicator. Arrow Right increases saturation, Arrow Up increases brightness. Step size should be meaningful (e.g., 1% per press, 10% with Shift).
  • Hue slider: Standard <input type="range"> or role="slider" with aria-valuemin="0", aria-valuemax="360", aria-valuenow, and aria-valuetext="Hue: 14 degrees (red-orange)".
  • Alpha slider: role="slider" with aria-valuemin="0", aria-valuemax="100", aria-valuetext="Opacity: 80%".
  • Swatches: Navigable with arrow keys (grid pattern). Each swatch has role="option" or role="radio" with aria-label="Red (#FF0000)" or similar.
  • Text inputs: Standard text input behavior with validation.
  • Escape closes the popover and returns focus to the trigger.
  • Tab moves between sub-controls within the popover.

Screen Reader Experience (WCAG 4.1.2, 4.1.3):

  • Announce color changes: when the user moves the spectrum indicator, announce the resulting color as text. Use aria-valuetext on sliders: "Hue: 200 degrees, approximately cyan".
  • For the 2D spectrum, aria-valuetext could describe: "Saturation 70%, Brightness 85%".
  • When a swatch is selected, announce: "Selected: Ocean Blue, #0077B6".
  • Announce format switches: "Switched to HSL format".

Color Vision Deficiency (WCAG 1.4.1):

  • Swatches should include a text label or tooltip with the color name/value — not just a colored square.
  • The selected swatch indicator (checkmark or ring) must not rely on color alone. A white checkmark icon works well.
  • Consider showing the hex/RGB value beneath each swatch for clarity.

Non-Text Contrast (WCAG 1.4.11):

  • The trigger swatch border must have ≥3:1 contrast against the background, especially when the selected color is very light (near-white). Always maintain a visible border: 1px solid var(--color-neutral-300).
  • Slider thumbs must have ≥3:1 contrast against the slider track. The hue slider track is a rainbow gradient, so the thumb needs a white fill with a dark border to remain visible at all hue positions.
  • Verify with the Contrast Checker.

Target Size (WCAG 2.5.8):

  • Swatches must be at least 24×24px. Smaller swatches are common in compact pickers but fail WCAG AA.
  • Slider thumbs must be at least 24×24px.
  • The spectrum indicator (circle) should have a generous hit area, even if the visual indicator is small.

Reduced Motion (WCAG 2.3.3):

  • If swatches animate on hover (scale, bounce), respect prefers-reduced-motion by disabling the animation.

Usage Guidelines

Do's

  • Always include a text input (hex/RGB) alongside visual pickers. This is both an accessibility requirement and a power-user expectation.
  • Show the current value as readable text — display the hex code next to or below the color swatch.
  • Provide preset swatches for common use cases. Most users don't need the full spectrum — curated options reduce cognitive load.
  • Validate text input — parse hex, RGB, and HSL formats gracefully. Accept #FFF, #FFFFFF, rgb(255,255,255), and white if possible.
  • Debounce onChange during drag — spectrum and slider dragging fires hundreds of events per second. Throttle to ~60fps for UI updates, and use onChangeEnd for expensive operations (API calls, re-renders).
  • Show a preview of how the selected color will look in context (text on background, button with that color, etc.).
  • Support copy/paste — let users paste a hex code directly into the input field.

Don'ts

  • Don't rely on color alone for communicating the selected value. Always show the hex/RGB text representation.
  • Don't use a full spectrum when swatches suffice — if the user is choosing between 8 brand colors, a grid of 8 swatches is better than a 220×220px gradient.
  • Don't forget the alpha slider for use cases involving transparency (overlays, shadows, backgrounds). But hide it when alpha isn't relevant.
  • Don't allow invalid color selections in contexts where contrast matters — if the user picks a text color, show a warning when it fails WCAG contrast against the background. Integrate the Contrast Checker logic inline.
  • Don't nest the picker too deep — opening a popover from within a modal from within a dialog creates z-index nightmares and traps focus in confusing ways.
  • Don't persist the eyedropper state — after one pick, return to normal mode. The EyeDropper API already handles this natively.

Integration with Color Tools

When building a color picker for a design system or theming tool, consider integrating with the Color Palette Generator to:

  • Auto-generate a full palette (50–900 shades) from a single selected color.
  • Show complementary, analogous, or triadic color suggestions.
  • Validate the generated palette against WCAG contrast requirements.

Code Snippets

html
<!-- Color Picker: Swatch + Hex Input -->
<div class="color-picker" id="color-picker">
  <label class="color-picker__label" id="cp-label">Brand Color</label>

  <div class="color-picker__trigger-row">
    <button
      type="button"
      class="color-picker__swatch-btn"
      id="cp-trigger"
      aria-label="Select brand color. Current: #6366F1"
      aria-haspopup="true"
      aria-expanded="false"
      style="background-color: #6366F1;"
    ></button>
    <input
      type="text"
      id="cp-hex-input"
      class="color-picker__hex-input"
      value="#6366F1"
      maxlength="7"
      aria-labelledby="cp-label"
      spellcheck="false"
    />
  </div>

  <!-- Swatches (shown inline or in popover) -->
  <div class="color-picker__swatches" role="listbox" aria-label="Preset colors" id="cp-swatches">
    <button role="option" aria-label="Red, #EF4444" aria-selected="false" class="color-picker__sw" style="background:#EF4444;" data-color="#EF4444"></button>
    <button role="option" aria-label="Orange, #F97316" aria-selected="false" class="color-picker__sw" style="background:#F97316;" data-color="#F97316"></button>
    <button role="option" aria-label="Yellow, #EAB308" aria-selected="false" class="color-picker__sw" style="background:#EAB308;" data-color="#EAB308"></button>
    <button role="option" aria-label="Green, #22C55E" aria-selected="false" class="color-picker__sw" style="background:#22C55E;" data-color="#22C55E"></button>
    <button role="option" aria-label="Blue, #3B82F6" aria-selected="false" class="color-picker__sw" style="background:#3B82F6;" data-color="#3B82F6"></button>
    <button role="option" aria-label="Indigo, #6366F1" aria-selected="true" class="color-picker__sw color-picker__sw--selected" style="background:#6366F1;" data-color="#6366F1"></button>
    <button role="option" aria-label="Purple, #A855F7" aria-selected="false" class="color-picker__sw" style="background:#A855F7;" data-color="#A855F7"></button>
    <button role="option" aria-label="Pink, #EC4899" aria-selected="false" class="color-picker__sw" style="background:#EC4899;" data-color="#EC4899"></button>
  </div>

  <div id="cp-status" aria-live="polite" class="sr-only"></div>
</div>

<style>
.color-picker__label {
  display: block;
  font-weight: 600;
  font-size: 0.875rem;
  margin-bottom: 0.375rem;
  color: var(--color-neutral-900);
}

.color-picker__trigger-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.color-picker__swatch-btn {
  width: 36px;
  height: 36px;
  border: 2px solid var(--color-neutral-300);
  border-radius: var(--radius-md, 8px);
  cursor: pointer;
  flex-shrink: 0;
  transition: transform 100ms ease;
}

.color-picker__swatch-btn:hover {
  transform: scale(1.05);
}

.color-picker__swatch-btn:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.color-picker__hex-input {
  width: 90px;
  height: 36px;
  padding: 0 0.5rem;
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-sm, 4px);
  font-family: monospace;
  font-size: 0.875rem;
  color: var(--color-neutral-900);
  text-transform: uppercase;
}

.color-picker__hex-input:focus {
  outline: none;
  border-color: var(--color-primary-500);
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}

.color-picker__swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.color-picker__sw {
  width: 28px;
  height: 28px;
  border: 2px solid transparent;
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  position: relative;
  transition: transform 100ms ease;
}

.color-picker__sw:hover {
  transform: scale(1.15);
}

.color-picker__sw:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.color-picker__sw--selected {
  border-color: var(--color-neutral-900);
}

.color-picker__sw--selected::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 14px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
</style>

<script>
const swatches = document.querySelectorAll(".color-picker__sw");
const hexInput = document.getElementById("cp-hex-input");
const trigger = document.getElementById("cp-trigger");
const status = document.getElementById("cp-status");

function selectColor(hex) {
  trigger.style.backgroundColor = hex;
  trigger.setAttribute("aria-label", "Select brand color. Current: " + hex);
  hexInput.value = hex;
  swatches.forEach((sw) => {
    const match = sw.dataset.color === hex;
    sw.classList.toggle("color-picker__sw--selected", match);
    sw.setAttribute("aria-selected", String(match));
  });
  status.textContent = "Selected: " + hex;
}

swatches.forEach((sw) => {
  sw.addEventListener("click", () => selectColor(sw.dataset.color));
});

hexInput.addEventListener("change", () => {
  const val = hexInput.value.trim();
  if (/^#[0-9A-Fa-f]{6}$/.test(val)) {
    selectColor(val.toUpperCase());
  }
});
</script>
tsx
import React, { useState, useCallback, useId } from "react";

interface ColorPickerProps {
  value?: string;
  defaultValue?: string;
  onChange?: (color: string) => void;
  swatches?: string[];
  label: string;
  disabled?: boolean;
  showInput?: boolean;
}

const DEFAULT_SWATCHES = [
  "#EF4444", "#F97316", "#EAB308", "#22C55E",
  "#3B82F6", "#6366F1", "#A855F7", "#EC4899",
  "#14B8A6", "#64748B", "#1E293B", "#FFFFFF",
];

export function ColorPicker({
  value: controlledValue,
  defaultValue = "#6366F1",
  onChange,
  swatches = DEFAULT_SWATCHES,
  label,
  disabled = false,
  showInput = true,
}: ColorPickerProps) {
  const id = useId();
  const [internal, setInternal] = useState(defaultValue);
  const color = controlledValue ?? internal;
  const [hexInput, setHexInput] = useState(color);
  const [announcement, setAnnouncement] = useState("");

  const selectColor = useCallback(
    (hex: string) => {
      const upper = hex.toUpperCase();
      setInternal(upper);
      setHexInput(upper);
      onChange?.(upper);
    },
    [onChange]
  );

  const handleInputBlur = () => {
    if (/^#[0-9A-Fa-f]{6}$/.test(hexInput)) {
      selectColor(hexInput);
      setAnnouncement(`Color set to ${hexInput.toUpperCase()}`);
    } else if (/^#[0-9A-Fa-f]{3}$/.test(hexInput)) {
      const expanded = "#" + hexInput[1] + hexInput[1] + hexInput[2] + hexInput[2] + hexInput[3] + hexInput[3];
      selectColor(expanded);
      setAnnouncement(`Color set to ${expanded}`);
    } else {
      setHexInput(color);
    }
  };

  const handleSwatchClick = (hex: string) => {
    selectColor(hex);
    setAnnouncement(`Selected ${hex}`);
  };

  const isLight = (hex: string): boolean => {
    const r = parseInt(hex.slice(1, 3), 16);
    const g = parseInt(hex.slice(3, 5), 16);
    const b = parseInt(hex.slice(5, 7), 16);
    return (r * 299 + g * 587 + b * 114) / 1000 > 186;
  };

  return (
    <div style={{ opacity: disabled ? 0.5 : 1, pointerEvents: disabled ? "none" : undefined }}>
      <label id={`${id}-label`} style={{ display: "block", fontWeight: 600, fontSize: "0.875rem", marginBottom: 4 }}>
        {label}
      </label>

      <div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.75rem" }}>
        <div
          aria-label={`Current color: ${color}`}
          style={{
            width: 36,
            height: 36,
            borderRadius: "var(--radius-md, 8px)",
            border: "2px solid var(--color-neutral-300)",
            backgroundColor: color,
            flexShrink: 0,
          }}
        />
        {showInput && (
          <input
            type="text"
            value={hexInput}
            onChange={(e) => setHexInput(e.target.value)}
            onBlur={handleInputBlur}
            onKeyDown={(e) => e.key === "Enter" && handleInputBlur()}
            aria-labelledby={`${id}-label`}
            maxLength={7}
            spellCheck={false}
            style={{
              width: 90,
              height: 36,
              padding: "0 0.5rem",
              border: "1px solid var(--color-neutral-300)",
              borderRadius: "var(--radius-sm, 4px)",
              fontFamily: "monospace",
              fontSize: "0.875rem",
              textTransform: "uppercase",
            }}
          />
        )}
      </div>

      {swatches.length > 0 && (
        <div role="listbox" aria-label="Preset colors" style={{ display: "flex", flexWrap: "wrap", gap: "0.375rem" }}>
          {swatches.map((hex) => (
            <button
              key={hex}
              type="button"
              role="option"
              aria-label={`${hex}`}
              aria-selected={color === hex.toUpperCase()}
              onClick={() => handleSwatchClick(hex)}
              style={{
                width: 28,
                height: 28,
                backgroundColor: hex,
                border: color === hex.toUpperCase() ? "2px solid var(--color-neutral-900)" : "2px solid transparent",
                borderRadius: "var(--radius-sm, 4px)",
                cursor: "pointer",
                position: "relative",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
              }}
            >
              {color === hex.toUpperCase() && (
                <span style={{ color: isLight(hex) ? "#000" : "#fff", fontSize: 14, textShadow: "0 1px 2px rgba(0,0,0,0.3)" }}>✓</span>
              )}
            </button>
          ))}
        </div>
      )}

      <div aria-live="polite" aria-atomic="true" style={{ position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0,0,0,0)" }}>
        {announcement}
      </div>
    </div>
  );
}

Design Systems

Design System Implementations

Material Design 3 doesn't include a dedicated color picker component in its specification. MUI provides a basic color input via <TextField type="color"> which renders the browser's native color picker. For richer implementations, the MUI ecosystem relies on third-party libraries like react-colorful or @uiw/react-color.

Ant Design provides a ColorPicker component (introduced in v5.5) with a full-featured panel: spectrum area, hue slider, alpha slider, format switcher (hex/RGB/HSB), preset swatches (presets prop with labeled groups), and a compact trigger swatch. It supports controlled/uncontrolled modes, allowClear, showText (display color value next to trigger), and trigger="hover" for opening on hover instead of click. The picker uses the HSB color model internally.

Radix UI and Headless UI do not provide color picker primitives. Color picking is considered application-level rather than a primitive UI component.

react-colorful is the most popular lightweight React color picker. At ~2 KB gzipped, it provides a spectrum + hue slider with zero dependencies. It exports components for different color models: HexColorPicker, RgbColorPicker, HslColorPicker, HsvColorPicker, and alpha variants. It's fully accessible with keyboard support on the spectrum and sliders. No swatch support — you'd build that separately.

@uiw/react-color is a comprehensive React color picker suite providing multiple picker styles: Sketch (Sketch app style), Chrome (Chrome DevTools style), Compact, Material, Wheel, Block, Github, and Slider. Each targets a different visual style and complexity level.

Figma, Sketch, and Adobe XD all use a spectrum + hue + alpha pattern with HSB/HSV as the primary color model, plus text inputs for hex and RGB. Figma adds an eyedropper and a document-colors swatch bar. These professional tools set user expectations for what a "good" color picker looks like.

Native HTML <input type="color"> provides a built-in color picker that varies by OS and browser. It's fully accessible, requires zero JavaScript, and is the simplest option — but it can't be styled, doesn't support alpha, and offers no swatches. Consider it as a progressive enhancement or fallback.

The Color Palette Generator on this site can be used alongside any color picker to generate full design token palettes from a single selected color.

Data InputColor ChooserColor Selector