Configured to work exclusively with Pretty Ugly Colors, DPS is a new syntax that makes using color tokens a breeze, no matter the theme.
Introduction
Why do we create so many tokens? Why are tokens different between systems? Why is managing tokens as stressful as working without them?
Token proliferation is making it harder for new designers to assimilate, and for existing designers—they're just fed up.
Dynamic Palette Syntax harnesses what developers cherish about Tailwind's utility classes while preserving the clean, semantic quality of HTML.
Less tokens, neater code, faster iterations.
Install
If you'd like to use this functionality Pretty Ugly Colors you can do so by adding it to your HTML file. Please note the following:
Adding the script:
html
<script src="node_modules/@razorloaf/pretty-ugly-colors/dist/js/runtime.min.js"></script>
Basics
Dynamic Palette Syntax, or DPS for short, is essentially a color transformation system that lets you modify colors on the fly using CSS variable syntax. Instead of having to define separate variables for every state (hover, active, etc.), you can derive them automatically.
The syntax leverages CSS custom properties combined with a lightweight JavaScript runtime that resolves transformative expressions at runtime.
Example:
css
/* Structure */
var(--token-name:transformation);
/* Usage */
var(--color-primary:up);
This expression instructs the system to retrieve the base color referenced by --color-primary and apply the up transformation, which increases the color's intensity by one shade in its predefined scale.
Features
Example:
css
/* Current range of modifiers */
var(--token-name:up);
var(--token-name:down);
var(--token-name:alpha);
var(--token-name:oklch);
var(--token-name:p3a);
var(--token-name:mono);
:up — Makes the color one shade darker
:down — Makes the color one shade lighter
:alpha — Uses the alpha variant for transparency
:oklch — Uses the OKLCH color space for vibrancy and gradient control
:p3a — Uses the Display-P3 alpha variant for vibrancy and transparency
:mono — Transforms color into neutral equivalent for disabled states
Parametrized Modifiers: You can specify how many steps to change
Example:
css
var(--token-name:up(3));
var(--token-name:down(2));
:up(n) — Goes up n number of shade levels (darker)
:down(n) — Goes down n number of shade levels (lighter)
Runtime Transformation: The DPS runtime processes your CSS after it loads and replaces the DPS expressions with actual color values.
Smart Token Resolution: DPS first checks if the color is a semantic token (--color-primary) and resolves it to its base color (blue-500).
Advanced: Chains
As you've probably seen transformations can be complex but extremely useful. Chains, or Chained Transformations, represent one of the most powerful aspects of Dynamic Palette Syntax, allowing you to compose multiple operations sequentially to achieve nuanced variations.
Understanding Chains
In DPS, a Chain applies multiple modifiers in sequence, with each transformation building upon the result of the previous one. The syntax follows this pattern:
Example:
css
var(--token-name:transform1:transform2:transform3);
The transformations are applied from left to right, with each operation taking the output of the previous one as its input. This sequential application creates a powerful composition system that can express complex color relationships.
Advanced: Chain Effects
As you've probably seen transformations can be complex but extremely useful. Chains, or Chained Transformations, represent one of the most powerful aspects of Dynamic Palette Syntax, allowing you to compose multiple operations sequentially to achieve nuanced variations.
Transform
This is one of the simplest chains allowing you to update the shade and add a slightly transparent feel to it. Our alpha variants are equal to our HEX value based on a pure white background for light themes and #121212 for dark.
Example:
css
var(--token-name:up:alpha);
var(--token-name:down:alpha);
Focus states that need to be lighter or darker but somewhat see-through
Hover states on elements that overlay other content
Great for theme switching as alpha variants mimic their HEX counterparts but will add a slightly transparent effect in dark mode
Stepping
This is a common chain that allows you to change the shade scale, either lighter or darker, as well as the color space.
Example:
css
var(--token-name:up(2):oklch);
var(--token-name:down(3):p3a);
Creating perceptually smooth gradients thanks to OKLCH
Ensuring color harmony when animating between states
Mono
Mono is a great transformation that makes it incredibly simple, and scalable, working with disabled states. Mono works by converting the token's assigned color and replacing it with the corresponding neutral shade.
Example:
css
var(--token-name:mono);
var(--token-name:up(2):mono);
var(--token-name:down(3):alpha:mono);
Removes all disabled-specific color tokens from your codebase
Automatically adjusts if the token's assigned color changes
Considerations
We'll talk about DPS implementation in the next section but when implementing chained transformations you must consider the following:
Examples
Let's take a look at common elements and components we can apply color transformations to to reduce token bloat. These are very generic examples and for educational purposes have been simplified.
Button:
css
:root {
--bgColor-dps-button: var(--blue-500);
--bgColor-dps-button-hover: var(--blue-700);
--bgColor-dps-button-active: var(--blue-800);
--bgColor-dps-button-disabled: var(--gray-500);
}
Button using DPS:
bash
:root {
--bgColor-dps-button: var(--blue-500);
}
.dps-button {
background-color: var(--bgColor-dps-button);
}
.dps-button:hover {
background-color: var(--bgColor-dps-button:up(2));
}
.dps-button:active {
background-color: var(--bgColor-dps-button:up(3));
}
.dps-button:disabled {
background-color: var(--bgColor-dps-button:mono);
}
Primary button uses the original token
Hover state utilizes the original token but is adjusted two shades darker
Active state is adjusted three shades darker
Disabled state transforms from blue-500 to neutral-500 (mono)
Input:
css
:root {
--fgColor-input: var(--neutral-900);
--fgColor-input-placeholder: var(--neutral-600);
--fgColor-input-disabled: var(--neutral-400);
--bgColor-input: var(--neutral-100);
--bgColor-input-disabled: var(--neutral-300);
--borderColor-input: var(--neutral-300);
--borderColor-input-hover: var(--neutral-700);
--borderColor-input-focus: var(--neutral-900);
--borderColor-input-disabled: var(--neutral-400);
}
Input using DPS:
css
:root {
--bgColor-input: var(--neutral-100);
--borderColor-input: var(--neutral-300);
--fgColor-input: var(--neutral-1200);
}
.dps-input {
background-color: var(--bgColor-input);
border-color: var(--borderColor-input);
color: var(--fgColor-input);
}
.dps-input:hover {
border-color: var(--borderColor-input:up(2));
}
.dps-input:focus {
border-color: var(--borderColor-input:up(2));
box-shadow: 0 0 0 3px var(--bgColor-input:up(3):alpha);
}
.dps-input:disabled {
background-color: var(--bgColor-input:up);
border-color: var(--borderColor-input:down);
color: var(--fgColor-input:down(3):alpha);
}
Normal state uses the original input tokens
Hover state uses the border color but one shade darker
Focus state uses neutral-500 with a transparent shadow using :alpha
Disabled state makes the background slightly darker, border lighter, and text semi-transparent
Footnotes
Dynamic Palette Syntax, or DPS, is configured to work with Pretty Ugly Colors and has no functionality implemented to work beyond that color system.
Licensed under MIT. See LICENSE file for complete terms.
While attribution is appreciated, it's not required for implementation in commercial projects.
Mid Engineering © 2025