Colors
Shilp CSS ships with a rich, carefully curated color system out of the box.
The default palette is derived from the excellent work done by Tailwind CSS and is suitable for a wide range of design styles, minimal, expressive, or system-heavy.
This palette is included as raw values as well as first-class design tokens.
Color Format
OKLCH by Default
All colors in Shilp CSS are defined in the oklch color format.
oklch works better, because it matches how people actually see color. When you
change lightness, the color really gets lighter or darker. Gradients look
smooth, not muddy, and tweaking color feels natural instead of guessy.
Compared to hex, rgb, or hsl, oklch simply produces colors that look
right, not just mathematically calculated right.
To know more, see:
Native HTML Colors
Shilp CSS also includes OKLCH equivalents for all native HTML named colors, such as orange, white, green, blue, gold, etc.
This allows you to use familiar color names. They behave like the rest of the system, predictable, themeable, and token-driven.
HTML colors names are split into words and organized as nested objects.
| Value (in oklch) | HTML named color | Shilp CSS Color |
|---|---|---|
73.1% 0.181 66.3 | orange | orange |
58.6% 0.199 45.4 | orangered | orange-red |
59.8% 0.157 65.6 | darkorange | orange-dark |
To know more, see:
Build-Time Conversion & Fallbacks
While most modern browsers began supporting the oklch color format around
May 2023, Shilp CSS’s compatibility baseline starts slightly earlier
January 31, 2023.
To ensure predictable behavior across all supported browsers, at build time, Shilp CSS uses Lightning CSS to transforms these values.
This means:
-
oklchtolabformat conversion for internal processinglabis a simpler Cartesian form, easier to clamp and serialize, and more widely supported by tooling
-
A
hexformat fallback is generated to ensure broad browser compatibility
This allows oklch to remain the authoring format, while the output stays safe
and compatible.
To know more, check:
Color Scales
Same as Tailiwind CSS, Every color in the default palette includes 11 steps,
with 50 being the lightest, and 950 being the darkest.
The scale gives you enough range to express hierarchy without inventing custom values.
See:
Adjusting The Opacity
You can adjust a color’s opacity using a variant.
| Color | Opacity |
|---|---|
@text color-primary; | 100% |
@text color-primary/50; | 50% |
The additional /50 is known as variant. which is to be appended to the
color utility.
Built For Theming
Colors are the most visible part of theming.
Brand And Semantic Colors
Shilp CSS strongly recommends styling with brand and semantic design tokens, not just raw color values.
Instead of writing:
color: orange;color: oklch(70.5% 0.213 47.604);color: oklch(theme(colors-orange));@text color-orange;
You use tokens like like primary, secondary, accent, base (neutral),
success, info, warning, and danger.
Each color group provides:
- a full
50–950scale - a default value (without the scale)
- a matching contrast text color for darker scales
- an alternate contrast text color for lighter scales
This keeps color usage consistent, intentional, easy to theme and refactor.
See: Brand and Semantic Color Reference
Color Roles
Brand and semantic colors (primary, base, success etc.) define your
palette.
Color role tokens define how your application uses that palette.
| Role | Purpose |
|---|---|
--bg | Background color |
--fg | Contrast text color for background color |
--muted | Muted color |
--muted-fg | Contrast text color for muted color |
--surface | Surface color |
--surface-fg | Contrast text color for surface color |
--border | Border color |
They are more of a usage-level tokens, not palette-level tokens.
Background Color + Contrast Text Color = Safe Contrast
The Layering Model
Shilp CSS theming works in layers:
- Raw palette tokens (color scales + html named colors)
- Brand and semantic tokens (
primary,success, etc) - Color roles tokens (
--surface,--border, etc) - Utilities consuming tokens
Each layer depends on the previous layer (order: 1 to 4).
You rarely touch layer 1. You theme mostly at layers 2 and 3.
How Color Tokens Work
Shilp CSS maps color tokens to CSS variables.
shilp.config.jsconst shilpConfig = { source: "react", extend: { theme: { colors: { primary: { // DEFAULT: "var(--primary)", fg: { DEFAULT: "var(--primary-fg)", alt: "var(--primary-fg-alt)", }, 50: "var(--primary-50)", 100: "var(--primary-100)", ... 950: "var(--primary-950)", } }, }, }, }; export default shilpConfig;
The actual values are defined in CSS:
colors.csshtml, :host { --primary: var(--primary-600); --primary-fg: var(--white); --primary-fg-alt: var(--black); --primary-50: theme(colors-orange-50); --primary-100: theme(colors-orange-100); --primary-200: theme(colors-orange-200); ... --primary-900: theme(colors-orange-900); --primary-950: theme(colors-orange-950); }
This separation allows runtime theme switching and safe refactors.
Inline Theme Function
Shilp CSS exposes all color tokens through the inline theme(...) function. You
can use it anywhere a value is expected.
.any-class { background-image: linear-gradient( in oklch to top left, oklch(theme(colors-primary)) 20%, oklch(theme(colors-accent-700) / 0.9) 50%, oklch(theme(colors-base-100)) 70% ); }
Customization
You can extend / override default colors in
shilp.config.js.
Colors are defined using nested objects. Each level of nesting adds an extra
step when accessing the color via @intent-name utilty; or theme(...).
| Location | Intent | Inline Theme Function |
|---|---|---|
shilpConfig.theme.colors.orange.600 | @text color-orange-600; | color: oklch(theme(colors-orange-600)); |
shilpConfig.theme.colors.html.red | @text color-html-red; | color: oklch(theme(colors-html-red)); |
shilp.config.jsconst shilpConfig = { source: "react", extend: { theme: { colors: { // you can add/override your colors here orange: { 600: "64.6% 0.222 41.116", }, }; }, }, }; export default shilpConfig;