Skip to content
TeaCSS documentation

Palette

Select semantic color roles and light or dark appearance at the document root.

Standard provides physical color families with 12 steps: 100, 150, 200, 300, 400, 500, 600, 700, 800, 850, 900, and 950. The interactive palette shows the actual source colors in light and dark appearance.

Start with semantic roles

Use roles for component surfaces, text, focus, and state. The defaults are:

Role Default palette Use
primary ink Primary actions and emphasis
neutral gray General surfaces, borders, and text
focused Follows global neutral Focus treatment
success jade Successful outcomes
warning amber Warnings
failure red Errors and destructive outcomes
general blue Informational state
html
<div class="bg-color:neutral-100 border-color:neutral-600 text-color:neutral-950">
  A surface that follows the selected neutral palette
</div>
Step range Typical role
100–150 Backgrounds
200–400 Interactive surfaces
500–700 Borders and accents
800–850 Solid treatments
900–950 Text

Steps guide selection; they do not guarantee contrast. Check the actual text/background pair in both appearances and do not communicate state through color alone. Fixed physical names such as teal-600 remain valid for content that requires that specific hue; reusable components should follow roles.

The default ink palette supplies gray surfaces and near-black 800/850 fills in light appearance, with near-white fills in dark appearance. Its 200 step remains a subtle surface. It has all 12 steps and is consumed through the existing primary role. gray and sage remain available.

TeaCSS 0.7.1 also sets lime-800 to Yiplex’s #C2D435 accent in both appearances. Its 850 hover is darker in light appearance and lighter in dark appearance. Those bright fills need dark text: use neutral-950 in light appearance and neutral-100 in dark appearance. For text on subtle surfaces, prefer the appearance-dependent lime-900 or lime-950.

Register palette choices

The CSS entry declares which built-in physical palettes a role may select:

css
@presets "standard,icons,official";
@primary "ink,gray,blue";
@neutral "gray,sage,slate";
@focused "gray,blue";
@success "jade,green";
@warning "amber,orange";
@failure "red,ruby";
@general "blue,cyan";
@teacss;

Lists register choices without changing the default. Their names must be built-in physical palettes; custom colors and role-to-role references cannot be registered as choices. Repeated lists are combined.

Absent role attributes use the ink/gray defaults even without candidate lists. Explicit root selections, including ink, require a matching list. To keep the earlier gray/sage combination when upgrading, register both palettes and select data-css-primary="gray" data-css-neutral="sage" on html; a list alone does not select them.

Choose a registered palette on <html>:

html
<html lang="en" data-css-primary="blue" data-css-neutral="slate" data-css-appearance="light">
  <body>...</body>
</html>

These attributes are document-wide. Descendant attributes do not create a local palette. Missing, empty, unknown, or unregistered role choices restore the configured defaults. focused follows the effective global neutral selection unless a valid focused selection or explicit default override is provided. No regeneration is needed to switch among registered choices.

Resolve light and dark appearance

Set data-css-appearance="light" or data-css-appearance="dark" on <html>. It selects color-mode values and drives @light and @dark conditions; @os-light and @os-dark independently follow the operating system. There is no implicit .dark class or descendant theme scope. Without a valid explicit appearance, neither @light nor @dark matches, while the configured base color table still applies.

Astra applications can place one AppearanceScript in <head> before styles and use AppearanceSwitch to manage the preference. See Astra for ownership and persistence. The root stores the resolved light or dark value; system is a preference that the manager resolves, not a third CSS appearance.

Add application colors

Register supported color values in the CSS entry:

css
@presets "standard";
@source "./src/**/*.{astro,html,js,jsx,ts,tsx}";
@custom {
  --color-brand-500: #0f766e;
}
@teacss;

This adds bg-color:brand-500 and text-color:brand-500. Custom names remain utility values; this does not add a selectable physical palette. @custom accepts supported theme namespaces. Ordinary application variables belong in native CSS or the $name:value utility. Color mode blocks can override colors; non-color values do not become per-mode theme settings.

Continue with Standard for properties and conditions.