Design
Colors & Theming
Theme-aware text colors, automatic dark mode, 120+ CSS custom properties, and the ability to create fully custom themes.
Colors
Text Color Utilities
Theme-aware semantic text color classes that adapt to light and dark mode automatically.
text-primary — Body text color (theme-aware)
text-secondary — Secondary/subdued text (theme-aware)
text-tertiary — Muted/tertiary text (theme-aware)
text-muted — Alias for text-tertiary
success — Success/positive state (green)
error — Error/destructive state (red)
| Class | Description |
|---|---|
text-primary | Body text color (theme-aware) |
text-secondary | Secondary/subdued text (theme-aware) |
text-tertiary | Muted/tertiary text (theme-aware) |
text-muted | Alias for text-tertiary |
text-inverse | Inverse text for dark backgrounds |
success | Green text for success/positive states |
error | Red text for error/destructive states |
Dark Mode
Toggle Dark Mode
ply respects prefers-color-scheme automatically. Force a
mode with data-theme on the html element.
Current: auto
<!-- Auto (follows OS) -->
<html>
<!-- Force light -->
<html data-theme="light">
<!-- Force dark -->
<html data-theme="dark">
<!-- Toggle with JavaScript -->
<script>
document.documentElement.dataset.theme =
document.documentElement.dataset.theme === 'dark'
? 'light' : 'dark';
</script> Custom Properties
CSS Custom Properties
Override --ply-* variables to create any theme. All
colors, backgrounds, borders, and component styles are customizable.
Backgrounds
| Variable | Default (Light) | Description |
|---|---|---|
--ply-bg-body | #ffffff | Page background |
--ply-bg-surface | #ffffff | Card/surface background |
--ply-bg-surface-alt | #f4f4f4 | Alternate surface |
--ply-bg-muted | #e0e0e0 | Muted background |
Text Colors
| Variable | Default | Description |
|---|---|---|
--ply-color-body | #161616 | Primary text |
--ply-color-headings | #161616 | Heading text |
--ply-color-secondary | #525252 | Secondary text |
--ply-color-muted | #767676 | Muted text (supplementary) |
--ply-color-placeholder | #a8a8a8 | Placeholder text |
--ply-color-text-inverse | #ffffff | Inverse (on dark bg) |
Interactive
| Variable | Default | Description |
|---|---|---|
--ply-color-link | #0f62fe | Link color |
--ply-color-link-hover | #0043ce | Link hover |
--ply-color-accent | #0353e9 | Accent/brand color — used by .color-accent and .bg-accent |
--ply-color-focus | #0f62fe | Focus ring |
--ply-color-input-border | #8d8d8d | Input borders |
--ply-color-input-bg | #f4f4f4 | Input background |
--ply-btn-default-bg | #0353e9 | Primary button & link color |
--ply-btn-secondary-bg | #393939 | Secondary button bg |
Typography
| Variable | Default | Description |
|---|---|---|
--ply-font-body | System sans-serif | Body text, form controls |
--ply-font-heading | System sans-serif | Headings (h1–h6) |
--ply-font-mono | System monospace | Code, pre, kbd, samp |
Navigation
| Variable | Default | Description |
|---|---|---|
--ply-nav-bg | #ffffff | Nav background |
--ply-nav-color | #161616 | Nav text |
--ply-nav-border | #161616 | Nav border |
--ply-nav-hover | #e8e8e8 | Nav hover |
--ply-nav-active-bg | transparent | Nav active background |
Color Surfaces & Borders
Theme-aware surface and border colors for each palette color. Pastel in light mode, dark muted in dark mode.
| Variable | Light | Dark | Use |
|---|---|---|---|
--ply-{color}-surface | Pastel | Dark muted | Card/badge background |
--ply-{color}-border | Light tint | Medium dark | Colored borders |
--ply-{color}-1 | Base | Lighter | Text on surface, icons |
--ply-{color}-2 | Darker | Medium | Emphasis |
--ply-{color}-3 | Darkest | Lightest | Subtle accent |
Available for: blue, red, green, yellow, indigo, purple, pink, orange, teal, cyan.
Inverse & Black
Inverse surfaces reference the text-color variables, so they flip opposite the
body automatically and follow any text-color override. Black stays
#000 in every mode.
| Variable | Light | Dark | Description |
|---|---|---|---|
--ply-bg-inverse | #161616 | #f4f4f4 | Surface opposite the body (= --ply-color-body) |
--ply-layer-inverse-0 | #161616 | #f4f4f4 | Base inverse layer (= --ply-color-body) |
--ply-layer-inverse-1 | #525252 | #c6c6c6 | Raised inverse layer (= --ply-color-secondary) |
--ply-color-black | #000000 | #000000 | Absolute black, mode-independent |
Border Radius
A radius scale plus semantic aliases. Change the scale once, or retarget a single component’s alias.
| Variable | Value | Description |
|---|---|---|
--ply-radius-none | 0 | Square |
--ply-radius-xs | 0.125rem | 2px |
--ply-radius-sm | 0.25rem | 4px |
--ply-radius-md | 0.5rem | 8px |
--ply-radius-lg | 0.75rem | 12px |
--ply-radius-xl | 1rem | 16px |
--ply-radius-full | 9999px | Pill / circle |
--ply-border-radius | = radius-sm | Default element radius |
--ply-btn-border-radius | = radius-full | Buttons (pill) |
--ply-label-radius | = radius-sm | Labels |
--ply-badge-radius | = radius-full | Badges (pill) |
--ply-input-radius | = radius-sm | Inputs |
Control Sizing
Shared by inputs, buttons, selects and textareas so a given size is the same
height across every control. Height is emergent
(padding-y × 2 + line-height), never a fixed dimension.
| Variable | Large | Default | Small | XSmall |
|---|---|---|---|---|
--ply-control-font* | 1.125rem | 1rem | 0.875rem | 0.75rem |
--ply-control-py* | 0.875rem | 0.625rem | 0.375rem | 0.25rem |
--ply-control-px* | 2rem | 1.5rem | 1rem | 0.75rem |
--ply-control-lh* | 1.75rem | 1.5rem | 1.25rem | 1rem |
Suffixes: -lg, none (default), -sm, -xs.
e.g. --ply-control-py-sm.
Spacing
| Variable | Value | Description |
|---|---|---|
--ply-space-xs | 0.25rem | 4px |
--ply-space-sm | 0.5rem | 8px |
--ply-space-md | 0.75rem | 12px |
--ply-space | 1rem | 16px — default unit |
--ply-space-lg | 1.5rem | 24px |
--ply-space-xl | 2rem | 32px |
--ply-space-xxl | 3rem | 48px |
Custom
Creating a Custom Theme
Define a new data-theme value and override the CSS custom
properties. This lets you create any brand theme while keeping
accessibility and all component styles working.
[data-theme="warm"] {
/* Backgrounds */
--ply-bg-body: #faf5f0;
--ply-bg-surface: #f5ebe0;
--ply-bg-muted: #e6d5c3;
/* Text */
--ply-color-body: #1c1917;
--ply-color-headings: #44240e;
--ply-color-secondary: #6b4226;
/* Buttons & Links */
--ply-btn-default-bg: #92400e;
--ply-btn-secondary-bg: #78350f;
--ply-btn-default-color: #fff;
/* Typography */
--ply-font-body: Palatino, "Palatino Linotype", Georgia, serif;
--ply-font-heading: Palatino, "Palatino Linotype", Georgia, serif;
/* Borders */
--ply-border-color: #d4a574;
--ply-border-radius: 0.375rem;
/* Navigation */
--ply-nav-bg: #f5ebe0;
--ply-nav-border: #c2956b;
--ply-color-focus: #92400e;
/* Inputs */
--ply-color-input-border: #c2956b;
--ply-color-input-bg: #faf5f0;
}
<html data-theme="warm"> Override as many or as few properties as you need. Any property you don't override keeps its default value. See the buttons page for how primary and secondary buttons respond to themes.
Palette
Color Palette
10 colors at 3 intensity levels, available as CSS custom properties. All values adapt to light and dark mode automatically.
blue
red
green
yellow
indigo
purple
pink
orange
teal
cyan
Color Surfaces
Theme-aware surface colors for cards, badges, and alerts. Pastel in light mode,
dark muted in dark mode. Pair -surface with -border for borders
and -1 for text.
blue
surface + border + -1
green
surface + border + -1
red
surface + border + -1
yellow
surface + border + -1
purple
surface + border + -1
/* Theme-aware colored card — works in light and dark mode */
.card-info {
background: var(--ply-blue-surface);
border: 1px solid var(--ply-blue-border);
color: var(--ply-blue-1);
}
.card-success {
background: var(--ply-green-surface);
border: 1px solid var(--ply-green-border);
color: var(--ply-green-1);
}
.card-danger {
background: var(--ply-red-surface);
border: 1px solid var(--ply-red-border);
color: var(--ply-red-1);
} Brand Background Classes
Four colors have utility classes for quick backgrounds. These are static — same in light and dark mode — and designed for white text.
Sass Palette
With npm install ply-css, you get the full Sass palette:
base, dark, light, and pastel variants for every color, plus a 10-step neutral scale.
@use "ply-css/src/scss/components/colors" as colors;
// Base
color: colors.$color-blue; // #2575ed
color: colors.$color-indigo; // #4f46e5
// Dark — deeper shade
color: colors.$color-blue-dark; // #1a52a5
// Light — softer tint
background: colors.$color-blue-light; // #92baf6
// Pastel — subtle background
background: colors.$color-blue-pastel; // #d3e3fb
// Neutrals (50–900)
background: colors.$color-neutral-100; // #f5f5f5
color: colors.$color-neutral-700; // #404040 Next
Next Steps
Explore the type scale for text styling, or learn the grid system for page layouts.