CSS Variables
Some framework CSS variables are yours to use; the rest are internal and can change at any time. This page draws that line, family by family. It also shows how the Paint API, themes, and the Sass source each use the public ones.
Who Reads, Who Writes
The public --* variables are shared ground:
Sass writes them, themes change them, and the Paint API reads them.
- Sass generates them. The SCSS source emits every variable with its per-device values, and a custom build can extend the set. See Sass API Sass API The framework SCSS source: architecture, cascade layers, and what a custom stack can build from it The Sass API is the framework's SCSS source, open since 3.2. These pages cover the build-your-own path: compiling from source, adding device profiles, and using the mixins in your own SCSS. A custom stack can also skip the build entirely and serve an official released build, which is what the TRMNL Platform always does. .
- Themes change them. A theme picks colors by name through the slot mixins and never writes raw values. See Themes Themes Visually customize any plugin with a drop-in stylesheet that recolors the whole screen Themes are a simple way to visually customize any TRMNL plugin. A theme adjusts the framework's colors (backgrounds, text, borders, chart colors) without touching plugin markup, and gracefully adapts to every supported device, from 1-bit ePaper to full color. and Authoring Themes .
- Paint reads them. TRMNLPaint turns what CSS computed into Fill, BorderFill, and TypeSpec objects for JavaScript. See Paint API Paint API TRMNLPaint: read the exact colors and patterns CSS paints right now, from JavaScript TRMNLPaint is the framework's JavaScript API for its paint: colors, border lines, and text styles. Ask it for any framework color and it returns what CSS would actually paint right now, with the device and the active theme already applied. Use it wherever JavaScript draws: charts, canvases, or your own rendering. .
The palette behind the variables is defined on
Colors
Colors
Complete palette definition: grayscale, chromatic hues, and semantic roles
The Colors system defines the complete palette for the framework: grayscale, chromatic hues, and semantic roles (primary, success, error, warning). Use these tokens with bg--, text--, and other utilities. See Background and Text Color for usage examples.
. Every variable
with its per-mode values is listed on
Tokens
Tokens
Complete CSS variable reference with root defaults, density, and bit-depth overrides
The Tokens reference lists every Framework CSS variable from _variables_root.scss and display overrides in _variables_overrides.scss. Use it to understand defaults, 2-bit visual/layout behavior, high-density typography, and 4-bit-and-up scaling.
.
Public Variables
A variable is public unless its name marks it as internal, and a release keeps every public name in
every published bundle. Read public variables with
var() in custom CSS or
cssVar() in JavaScript, and reference them
from theme slots.
- Palette:
--black,--white, the--gray-*ladder, and one ladder per hue:--red-*,--orange-*,--yellow-*,--lime-*,--green-*,--cyan-*,--blue-*,--violet-*,--purple-*,--pink-*. - Semantic roles: the
--color-*family, which holds the roles (--color-primary,--color-success,--color-error,--color-warning) and the palette-mode ids. Hues live in the palette ladders above. - Geometry and scale:
--screen-*,--gap-*,--rounded-*, and the resolved--ui-scale,--content-scale, and--text-ui-scalefactors. - Component tokens: the families components read, from
--title-bar-*to--progress-*, all listed on Tokens Tokens Complete CSS variable reference with root defaults, density, and bit-depth overrides The Tokens reference lists every Framework CSS variable from_variables_root.scssand display overrides in_variables_overrides.scss. Use it to understand defaults, 2-bit visual/layout behavior, high-density typography, and 4-bit-and-up scaling. .
The --framework-* channels
get their own section below because the theme layer and the runtime write them.
/* Custom plugin CSS: reference public variables freely. */
.stat-card {
padding: var(--gap);
border-radius: var(--rounded);
}
// JavaScript: read the same variable at runtime.
var gap = TRMNLPaint.cssVar("--gap", { el: "my-chart" });
Framework Channels and Slots
The --framework-* families carry the current
paint between themes, components, and the runtime. They are public names: the minifier renames only
the internal families below, so a theme, a plugin stylesheet, or
cssVar() can read them in any build.
- Semantic channels:
--framework-semantic-{channel}-*for canvas, surface, backdrop, fill-strong, fill-muted, fill-soft, text-primary, text-secondary, text-inverse, stroke-contrast, border-strong, border-muted, and icon. A channel carries its whole paint: backgrounds have-bg-colorand-bg-image, text adds-text-underand-text-clipto its color and image, and borders carry-border-color,-border-image, and-border-size. - Role aliases: one flat color per role, resolved from the matching channel:
--framework-canvas-bg,--framework-surface-bg,--framework-backdrop-bg,--framework-text-primary,--framework-text-secondary,--framework-text-inverse,--framework-border-strong,--framework-border-muted,--framework-outline-strong,--framework-stroke-contrast,--framework-fill-strong,--framework-fill-muted,--framework-fill-soft. They drop the dither image, so use them only where a single color is what you want. - Component slots:
--framework-slot-{slot}-*, one group per component surface (title bar, screen backdrop, item meta, progress, table, label). A slot repaints one surface without moving a whole channel. See Theme Slots Theme Slots Every part of a screen a theme can recolor, from whole-screen colors down to single components, utilities, borders, and chart series This page lists every slot: each part of a screen a theme can recolor, and the mixin that sets it. A slot takes a framework token, not a raw color, so whatever you map still renders correctly on every device. . - Chart ramp:
--framework-chart-series-{i}-colorand--framework-chart-series-{i}-imagefor series indexes 0 to 15, plus--framework-chart-series-spanfor the number of entries JavaScript spreads series across. See Painting Charts Painting Charts Chart series colors for the current device, mode, and theme, with Highcharts adapters These functions pick the colors for a chart. Ask for series 2 of 5 and you get its paint, correct for the current device, mode, and theme. Adapters then turn each answer into the exact option Highcharts expects. . - Border render contract:
--framework-border-render-*(width,height,view-box,stroke,path-1,path-2,color-1,color-2): the SVG drawing instructions the framework declares for each border, which the Paint API copies into charts. See Painting Borders Painting Borders Read framework border lines as BorderFill objects, for your own lines and Highcharts axes These functions tell you exactly how the framework draws a border line. Use them so lines you draw yourself, or Highcharts axes and grid lines, match the borders around them. . - Icon source:
--framework-icon-srcholds the URL animage--adaptiveelement is masked with. The runtime writes it as an inline style, and markup can set it directly. See Image Image Place images with size, object fit, dithering, inversion, and adaptive icon utilities Place images on a screen and control their size, object fit, and inversion. On 1-bit displays, dithering arranges black and white pixels so an image still reads as shades of gray. .
Themes write these through the slot mixins, where one call fills a whole channel or slot. Setting a single
name by hand leaves the rest of its group behind, so plugin markup sets only
--framework-icon-src.
Internal Variables
Six name families are implementation details. The minified bundle
(plugins.min.css, the file production serves)
renames them to --_tn* names. Do not read or
set them; they can change or disappear in any release.
--_*: module-private helpers scoped to one component's rules.--framework-internal-*: plumbing that carries resolved values between framework layers.--tile-*: the generated dither tile assets.--bline-{n}: deduplicated border line gradients the border pipeline references.--border-*: the border pipeline, except the theme-contract names below.--tn-*: engine plumbing, except--tn-text-stroke-color,--tn-text-stroke-widthand--tn-text-stroke-radius, which the runtime reads.
The development build and the readable plugins.css
keep the source names, so you will see them in devtools. Treat them as off-limits anyway.
Framework-owned Paint Variables
The --bg-* and
--text-* families keep their names in every
build, but the framework's rendering owns them. They encode how each device prints: dithered down
to the panel's inks where needed, exact colors on full color.
Three border families survive the rename because the theme contract preserves them: the numbered slots
--border-1-h-* through
--border-7-v-*, the
--border-token-* names a shipped theme
references, and --border-line-dark /
--border-line-light. Everything else under
--border-*, including all the
--border-step-* names, is renamed in released
bundles.
Never set them from a plugin or a theme; the theme linter rejects any theme that tries. To consume the resolved paint from JavaScript, go through Paint API Paint API TRMNLPaint: read the exact colors and patterns CSS paints right now, from JavaScript TRMNLPaint is the framework's JavaScript API for its paint: colors, border lines, and text styles. Ask it for any framework color and it returns what CSS would actually paint right now, with the device and the active theme already applied. Use it wherever JavaScript draws: charts, canvases, or your own rendering. instead of reading them raw.