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-none0Square
--ply-radius-xs0.125rem2px
--ply-radius-sm0.25rem4px
--ply-radius-md0.5rem8px
--ply-radius-lg0.75rem12px
--ply-radius-xl1rem16px
--ply-radius-full9999pxPill / circle
--ply-border-radius= radius-smDefault element radius
--ply-btn-border-radius= radius-fullButtons (pill)
--ply-label-radius= radius-smLabels
--ply-badge-radius= radius-fullBadges (pill)
--ply-input-radius= radius-smInputs

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.125rem1rem0.875rem0.75rem
--ply-control-py* 0.875rem0.625rem0.375rem0.25rem
--ply-control-px* 2rem1.5rem1rem0.75rem
--ply-control-lh* 1.75rem1.5rem1.25rem1rem

Suffixes: -lg, none (default), -sm, -xs. e.g. --ply-control-py-sm.

Spacing

Variable Value Description
--ply-space-xs0.25rem4px
--ply-space-sm0.5rem8px
--ply-space-md0.75rem12px
--ply-space1rem16px — default unit
--ply-space-lg1.5rem24px
--ply-space-xl2rem32px
--ply-space-xxl3rem48px

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

surface
-1
-2
-3
border

red

surface
-1
-2
-3
border

green

surface
-1
-2
-3
border

yellow

surface
-1
-2
-3
border

indigo

surface
-1
-2
-3
border

purple

surface
-1
-2
-3
border

pink

surface
-1
-2
-3
border

orange

surface
-1
-2
-3
border

teal

surface
-1
-2
-3
border

cyan

surface
-1
-2
-3
border

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.

.bg-blue
.bg-red
.bg-green
.bg-yellow

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.