Appearance
Colors
Define colors in any format - they'll be automatically converted to OKLCH. You can compose colors from the palette into gradients and themes.
typescript
export default defineConfig({
colors: {
palette: {
value: {
simple: {
value: {
white: "oklch(100% 0 0)",
black: "#000",
green: { rgb: [0, 255, 0] },
blue: { hsl: [240, 100, 50] },
violet: { oklch: "oklch(0.7 0.2 270)" },
red: { hex: "#FF0000" },
},
},
another: {
value: {
yellow: { hex: "#FFFF00" },
cyan: { hex: "#00FFFF" },
},
settings: {
selector: ":root.Another",
},
},
},
},
gradients: {
value: {
"white-green": {
value: {
primary: {
value: "linear-gradient(to right, var(--c1), var(--c2))",
variables: {
"c1": "palette.simple.white",
"c2": "palette.simple.green",
},
},
},
},
},
},
theme: {
light: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.simple.white",
2: "gradients.white-green.primary", //Reference the color name directly.
},
settings: {
variantNameOnly: true,
},
},
},
},
dark: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.another.yellow",
2: "palette.another.cyan",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
atRule: "@media (prefers-color-scheme: dark)",
},
},
pink: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.simple.red",
2: "palette.simple.violet",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
selector: ".ThemePink",
},
},
},
},
});This will generate the following CSS :
css
/*____ CSSForge ____*/
:root {
/*____ Colors ____*/
/* Palette */
/* simple */
--palette-simple-white: oklch(100% 0 0);
--palette-simple-black: oklch(0% 0 0);
--palette-simple-green: oklch(86.644% 0.29483 142.49535);
--palette-simple-blue: oklch(45.201% 0.31321 264.05202);
--palette-simple-violet: oklch(70% 0.2 270);
--palette-simple-red: oklch(62.796% 0.25768 29.23388);
/* Gradients */
/* white-green */
--gradients-white-green-primary: linear-gradient(to right, var(--palette-simple-white), var(--palette-simple-green));
/* Themes */
/* Theme: light */
/* background */
--primary: var(--palette-simple-white);
--secondary: var(--gradients-white-green-primary);
/* Theme: dark */
@media (prefers-color-scheme: dark) {
/* background */
--primary: var(--palette-another-yellow);
--secondary: var(--palette-another-cyan);
}
}
/* another */
:root.Another {
--palette-another-yellow: oklch(96.798% 0.21101 109.76924);
--palette-another-cyan: oklch(90.54% 0.15455 194.76896);
}
/* Theme: pink */
.ThemePink {
/* background */
--primary: var(--palette-simple-red);
--secondary: var(--palette-simple-violet);
}The another palette is emitted under :root.Another, so the element carrying the theme class has to be the root element:
html
<html class="Another">Custom property references are substituted when the alias is computed, before inheritance. --primary: var(--palette-another-yellow) is computed on :root, so --palette-another-yellow has to be defined on :root as well. Scoping the palette to :root.Another keeps both declarations on the same element; a theme class on a descendant leaves --primary invalid at computed-value time, and every var(--primary, fallback) reference uses its fallback.
Color formats for browsers without oklch
Palette colors are generated in OKLCH. A custom property accepts any token stream, so a browser without oklch() support still parses --palette-coral-100: oklch(...) and only fails when the value is used as a color. Set formats to generate the same color in sRGB formats, so the unsupported browser keeps a usable color and non-CSS consumers read the value they need:
typescript
export default defineConfig({
colors: {
palette: {
value: {
coral: { 100: { hex: "#FF7F50" } },
coralDark: {
value: { 100: { hex: "#FF6347" } },
settings: { atRule: "@media (prefers-color-scheme: dark)" },
},
},
settings: {
color: {
formats: {
hex: { string: true, digits: true, number: true },
rgb: { string: true, array: true },
},
fallback: "hex",
},
},
},
},
});This will generate the following CSS :
css
/*____ CSSForge ____*/
:root {
/*____ Colors ____*/
/* Palette */
/* coral */
--palette-coral-100: oklch(73.511% 0.16799 40.24666);
/* coralDark */
@media (prefers-color-scheme: dark) {
--palette-coralDark-100: oklch(69.622% 0.19552 32.32143);
}
}
@supports not (color: oklch(0% 0 0)) {
:root {
/* coral */
--palette-coral-100: #ff7f50;
}
}
@media (prefers-color-scheme: dark) {
@supports not (color: oklch(0% 0 0)) {
:root {
/* coralDark */
--palette-coralDark-100: #ff6347;
}
}
}| Format | Output | Value |
|---|---|---|
hex | string | "#ff7f50" |
hex | digits | "ff7f50" |
hex | number | 16744272 (0xff7f50) |
rgb | string | "rgb(255 127 80)" |
rgb | array | [255, 127, 80] |
A format set to true generates its CSS value (string). A color with alpha carries it in every output: #ff7f50aa, ff7f50aa, 0xff7f50aa, rgb(255 127 80 / 0.667) and [255, 127, 80, 0.667].
Every format also takes an alpha policy: true (the default) keeps the alpha the color carries, a number between 0 and 1 generates that format at that opacity, and false rejects a color that carries alpha and drops the alpha from the output. The oklch() value keeps the alpha the color carries, so a format that sets an alpha is generated at that opacity alone.
fallback names the format whose string value, including its alpha policy, becomes the declaration for browsers without oklch() support. It defaults to the first generated format, has to be generated with its string output, and false emits no declaration so the formats only reach the tokens. The declaration is gated by @supports not (color: oklch(0% 0 0)) and emitted after the root block, because a custom property accepts any token stream and the later declaration wins wherever the modern value is unsupported. It mirrors the color's atRule and selector, so it only overrides the declaration it stands in for.
The palette settings cover every color, and a color replaces them in its own settings, so a color that only sets fallback keeps the palette's formats. The JSON, TypeScript and Style Dictionary tokens carry the generated values in a color object, keyed by format and output:
json
{
"key": "--palette-coral-100",
"value": "oklch(73.511% 0.16799 40.24666)",
"variable": "--palette-coral-100: oklch(73.511% 0.16799 40.24666);",
"color": {
"hex": { "string": "#ff7f50", "digits": "ff7f50", "number": 16744272 },
"rgb": { "string": "rgb(255 127 80)", "array": [255, 127, 80] }
}
}Setting the palette formats needs the settings key next to value; a color that carries settings is written with the value wrapper.
The palette is the only family that converts the colors it is given, so it is the only one that generates these formats. Themes, gradients and primitives keep their authored values, and they use the palette value through the var(--palette-...) references they already compose with. An oklch() written directly into a theme or gradient value stays as it is.
Condition
You can conditionnally apply colors, gradients or themes by setting the atRule or the selector properties. Your variables will be wrapped within :root and the selectors will be placed outside of it.
Theme: Variant Name Only
When working with themes, you can choose to only include the variant name in the CSS variable name by setting variantNameOnly: true in the color definition settings. This is usually used in combination with selector to conditionnally apply themes.
- Default:
--theme-${themeName}-${colorName}-${variantName} - VariantOnly Name:
--${variantName} - Path :
theme.${themeName}.${colorName}.${variantName}