Chroma Panel

Search documentation

Find a page or section

Set CSS variables on .cp-root to change how the panel looks.

.cp-root {
  --cp-accent: #e5484d;
  --cp-radius-lg: 4px;
  --cp-width: 280px;
}

Anything you do not set keeps its default. The panel follows the system color scheme unless you pass theme.

The full set

.cp-root {
  --cp-surface: #ffffff;
  --cp-surface-raised: #f4f4f6;
  --cp-border: #d6d6da;
  --cp-text: #1c1c1e;
  --cp-text-muted: #6b6b70;
  --cp-accent: #2d7ff9;
  --cp-focus: #2d7ff9;
  --cp-radius-lg: 16px;
  --cp-radius: 10px;
  --cp-width: 320px;
  --cp-disc-size: 196px;
  --cp-panel-h: 344px;
  --cp-control-height: 32px;
}

Two are worth knowing about before you change them.

--cp-control-height sizes the tab bar, the text inputs, the eyedropper and the footer swatch together, so one value scales every control at once.

--cp-panel-h is the height set aside for the mode content. It is the same in every mode, which is what stops the panel resizing when you switch tabs. Content taller than it scrolls. Set it to auto if you would rather each mode sized itself, and accept that the panel will jump.

Fitting a container

The panel is a fixed 320px wide and reserves a fixed height for its mode content. Both are variables, so it can be made to follow whatever box you put it in — this is what the cards on the home page do.

<ChromaPanel
  style={{
    "--cp-width": "100%",
    "--cp-panel-h": "auto",
  }}
/>

--cp-width: 100% lets the panel fill its parent. Nothing else has to change: the wheel is sized min(100%, var(--cp-disc-size)), so it scales down with the panel rather than overflowing.

--cp-panel-h is the height set aside for the mode content, and it is the one worth understanding:

ValueWhat happens
a length, the defaultEvery mode is that tall, so switching tabs never resizes the panel. A mode with less content than that shows empty space below it.
autoEach mode is as tall as its own content — no empty space, but the panel resizes when you switch tabs.

Showing a single mode, auto is almost always what you want: there is nothing to switch to, so the reserved height only leaves a gap.

Capping a tall mode

A length only caps the content when the panel has a height to divide up. With an auto-height panel the content grows past it instead. Give the panel a height as well and the mode content scrolls within it — .cp-panel-host is already overflow-y: auto.

// Fills its container, and scrolls the palette rather than growing the page.
<ChromaPanel
  modes={["palettes"]}
  style={{ "--cp-width": "100%", height: 420 }}
/>

If the panel looks wrong

The stylesheet lives in @layer chroma-panel, so your CSS always wins. That also means CSS you did not aim at the picker wins. Any unlayered element rule in your app beats every rule here, however specific:

/* This restyles the picker's swatches and tabs too. */
button {
  border-radius: 7px;
}

If the geometry looks off, look for a rule like that first. Scope it, or put your resets in a layer:

@layer reset, chroma-panel, utilities;

Loading the CSS yourself

For a strict style-src policy, or to extract critical CSS:

import "chroma-panel/styles.css";
 
<ColorInput injectStyles={false} />;

Injection is keyed on getRootNode(). The picker works inside a shadow root or an iframe, and many panels still produce one <style> element.

This does not shrink your bundle

injectStyles={false} only stops the panel writing a <style> tag. The CSS is imported by the module either way. Use it for CSP or critical CSS.

API reference

Styling functions

function injectStyles(css: string, id: string, node?: Node | null): void

Writes the stylesheet into the document, or into the shadow root the panel is inside. A no-op during server rendering, and when injectStyles={false}.

function setStyleNonce(provider: string | (() => string | undefined)): void

Sets the nonce put on the injected <style> element, for a strict style-src policy.

CSS variables

VariableDescription
--cp-accentSelection rings and the active tab.
--cp-borderHairlines between parts.
--cp-control-heightSizes the tab bar, the text inputs, the eyedropper and the footer swatch together, so one value scales every control at once.
--cp-disc-sizeDiameter of the colour wheel.
--cp-focusThe focus ring.
--cp-panel-hHeight reserved for the mode content. It is the same in every mode, which is what stops the panel resizing when you switch tabs. Set it to auto to let each mode size itself.
--cp-radiusCorner radius on controls inside the panel.
--cp-radius-lgThe panel's own corner radius.
--cp-surfaceThe panel background.
--cp-surface-raisedInputs, the tab bar and other raised areas.
--cp-textPrimary text.
--cp-text-mutedLabels and secondary text.
--cp-widthPanel width.