Border

Draw a horizontal or vertical rule on any element with the border--h and border--v utilities, named on the same 10 to 75 shade scale as backgrounds. On 1-bit displays a step renders as a dither pattern of black and white pixels, so a rule can read as gray. 4-bit and full-color screens draw all 14 steps; the other rails pair them onto seven levels.

#

Usage

Use directional step selectors: border--h-{step} and border--v-{step} with steps 10 to 75 (the background utility shade scale), plus semantic border--h-black / border--h-white. Borders render grayscale by default; themes repaint the whole rail.

4-bit and full-color screens give each of the 14 steps its own art. Everywhere else (the default rail, 1-bit, 2-bit, and the limited palettes) the steps pair onto the seven border levels, so border--h-40 and border--h-45 draw the same line.

Pick steps two apart when two rules have to read differently on a 1-bit panel.

The numbered level classes (border--h-1 through border--h-7, and their vertical counterparts) are deprecated and will be removed in Framework 4.0. Prefer step selectors in new markup.

#

Horizontal Borders

10
15
20
25
30
35
40
45
50
55
60
65
70
75
10
15
20
25
30
35
40
45
50
55
60
65
70
75
TRMNL Logo Horizontal Borders
<div class="border--h-10">Dark border</div>
<div class="border--h-45">Mid border</div>
<div class="border--h-75">Light border</div>
#

Vertical Borders

10
15
20
25
30
35
40
45
50
55
60
65
70
75
10
15
20
25
30
35
40
45
50
55
60
65
70
75
TRMNL Logo Vertical Borders
<div class="border--v-20">Vertical border</div>
<div class="border--v-65">Vertical border</div>
#

Themed Borders

There are no per-hue border classes: the step rail renders the classic patterns by default, and a theme recolors them (and .divider) without changing their geometry via theme-slots.utility-remap-border-grayscale($hue, $side). The dark side paints black-on-hue, bright paints hue-on-white. Pick a Style in the screen picker to watch the rails above repaint.

The 2-bit rail is the exception: its four tones are literal in the line data, so a hue remap leaves it black, white and two grays. That is deliberate, since a hue quantizes to gray on a 4-tone panel anyway.

A theme that wants to move the 2-bit rail names levels instead, with theme-slots.utility-border-level($level, $dir, $from-level), the way the shipped Dark theme does. See Theme Slots .

@include theme-slots.utility-remap-border-grayscale("yellow", $side: "dark");
@include theme-slots.utility-remap-border-grayscale("red", $side: "bright");
#

Black & White Borders

Semantic border--h-black / border--h-white borders adapt to themes automatically. They resolve through framework semantic fill tokens, so they always represent the strongest and softest fill in the current theme context.

black
white
black
white
TRMNL Logo Black & White Borders
<div class="border--h-black">Black border (strongest fill)</div>
<div class="border--h-white">White border (softest fill)</div>
<div class="border--v-black">Black vertical border</div>
<div class="border--v-white">White vertical border</div>
#

Borders in JavaScript

Border rails are readable from JS through the paint API: TRMNLPaint.border(spec, { dir }) resolves a step, or the literal 'black' / 'white' rails straight from the live cascade (theme tinting, bit depth and dark mode included), and applyBorder() paints it onto a node. Because these fill-backed utilities carry real ink in every mode, they are the reliable hairline source for JS-drawn visuals like chart grids. See Painting Borders .