Rendering Modes
A rendering mode is the class that tells a screen what its panel can print. Three grayscale tiers cover the panels with no color, one class per palette covers the color panels, and the mode class publishes its own paint depth for the JavaScript runtime to read.
The three grayscale tiers
A grayscale screen carries one tier class. The class names how many grays the panel prints, and it picks both the paint rail and a set of display variables.
screen--1bit: every gray token paints as a dither pattern of black and white pixels, borders and text fills included. The root display variables apply unchanged.screen--2bit: tokens still dither, between four gray tones instead of two. Table and progress metrics scale with the interface.screen--4bit: every gray token paints as a solid, and each border step gets its own shade instead of two steps sharing one. The title bar drops its pixel-font padding offset and its text stroke thins.
All three tiers resolve a chromatic token to its gray fallback, so a theme hue never reaches a panel that cannot print it.
The demo below labels the tier it is rendering on. Switch device in the Device Preview to see the same screen on each one.
<!-- Two grays: the fills dither -->
<div class="screen screen--ogv2 screen--2bit">...</div>
<!-- Sixteen grays: the fills paint as solids -->
<div class="screen screen--v2 screen--4bit">...</div>
The color modes
A color panel carries a palette class in place of a tier class. Two families cover them.
-
One class per limited ink set
(
screen--color-3bwr,screen--color-3bwy,screen--color-4bwry,screen--color-6a,screen--color-7a): every framework token, grayscale rail included, dithers down to that palette's fixed inks. -
screen--color-fullfor 12-bit and 24-bit displays: every token paints at its actual hex, with no ink remap and no dithering.
Paint is palette-driven. The palette selected for a device decides which class the screen wears, and the class decides the rail. Color Palettes Color Palettes Every palette a screen can carry: grayscale tiers, limited ink sets, and full color, with the class each one maps to A palette tells a screen which inks its panel can print. Four grayscale palettes map onto the bit-depth classes, five limited color palettes dither every framework token down to a fixed ink set, and screen--color-full paints every token at its actual hex on 12-bit and 24-bit displays. lists every palette and the class it maps to.
<!-- Seven inks: bg--red-60 dithers between the panel's inks -->
<div class="screen screen--inkplate_6_color screen--color-7a">...</div>
<!-- Full color: bg--red-60 paints that exact hex -->
<div class="screen screen--generic_16_9 screen--color-full">...</div>
How the runtime learns the depth
The rule that selects a screen's paint rail also publishes that rail's depth as
--framework-bit-depth. The JavaScript runtime
reads the resolved value and never parses a class name, so a palette added in CSS reaches it with no
JavaScript change.
| Mode class | Published depth |
|---|---|
| No mode class | 1 |
screen--1bit |
1 |
screen--2bit |
2 |
screen--4bit |
4 |
| Any limited palette class | 4 |
screen--color-full |
12 |
The depth describes the rail, not the panel's storage. A limited palette prints solid inks the way the 4-bit rail prints solid tokens, so it publishes 4. A screen with no mode class publishes 1, because an unstated device is treated as the most constrained one.
Every mode rule carries the same specificity, so a screen wearing two mode classes reports the rail that
actually painted. screen--2bit screen--color-7a
paints palette inks and publishes 4.
Runtime engines gate on the published value: pixel-perfect fonts stand down at 4 and up, and the even index-width pin stops at 2 and up. See Framework Runtime Framework Runtime How the runtime applies layout, clamping, overflow, and presentation adjustments at render time Different devices have different, fixed amounts of screen space. The Framework Runtime fills that space when a plugin layout renders, doing the heavy, repetitive measuring and fitting for you. Expand the "Framework Runtime" panel under any example on this site to see the stats for that render. , or Paint API Paint API TRMNLPaint: read the live CSS cascade from JavaScript to resolve framework colors and tile patterns TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose. to read the variable from your own JavaScript.
Where the numeric variants stop
Utility classes take three numeric variant prefixes:
1bit:,
2bit:, and
4bit:. They end at 4-bit because grayscale glass
ends at 16 levels, so those three cover every grayscale panel.
Color is a separate axis, and no numeric variant matches a color screen. Target the color modes from SCSS
instead, with the for-color-palette($id) and
for-color-full mixins on
Sass Mixins
Sass Mixins
Screen-targeting mixins and scale functions for authoring device-aware SCSS
The screen mixins generate device-aware rules from the same grammar the responsive utility classes use: size, orientation, and bit depth. The scale functions wrap pixel values so custom CSS scales with the device like framework CSS does.
.
<!-- A dense dither needs a lighter shade to stay readable -->
<div class="layout bg--gray-65 2bit:bg--gray-75 4bit:bg--gray-70">...</div>
Do not build on screen--8bit or
screen--16bit.
Both are compatibility aliases scheduled for removal. They take the 4-bit display variables and the 4-bit
paint rail, though they publish their own number as the depth rather than 4.
Nothing above 4-bit grayscale needs them. The axis above 16 grays is color, through
screen--color-full.
Responsive Responsive Adapt styles to the device's size class, orientation, and bit depth using variant prefixes The Responsive system adapts a layout to the device it renders on. Size-based breakpoints follow the size class each device carries, and Bit-depth variants follow its color capabilities. Combine them to control how your content appears across TRMNL's range of devices. covers the full variant grammar, including how bit-depth prefixes combine with breakpoints and orientation.
Chart series per mode
Chart series colors follow the mode too. Grayscale tiers and limited palettes draw from the shade ladder, which opens on the screen's ink and steps toward its canvas.
screen--color-full draws from a categorical color
ramp instead: the ink, then seven hues in a fixed order, with steps picked for the light and dark ground
separately. A theme's own ramp still wins over both.
Painting Charts Painting Charts Chart series colors from the framework ramp, with Highcharts adapters The chart resolvers pick evenly spaced series colors from the framework chart ramp, resolved through the live cascade. Adapters convert the resulting Fills into Highcharts color options. resolves the active ramp from JavaScript, and Chart Chart Visualize data optimized for 1-bit rendering With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs. covers the markup.
Related APIs
Reading variables from JavaScript
cssVar(name, { el }) reads any variable on this page
back from the live cascade, theme and mode overrides included. The CSS stays the source of truth; nothing is
duplicated in JavaScript. See
Paint API
Paint API
TRMNLPaint: read the live CSS cascade from JavaScript to resolve framework colors and tile patterns
TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose.
for the full paint surface.
var gap = TRMNLPaint.cssVar("--gap", { el: "my-chart" });