Skip to the page
TACTILE UI

Kit part · Scroll areas

Scroll area

A region that scrolls, with its scrollbar made as a machined rail: a groove cut into the plate and a thumb like a fader cap riding in it. Scrolling itself is the browser’s own.

Element
<div tabindex="0">
Needs
kit.css
Rules
scroll-area.rules.md · 4
Finishes
Aluminium · Graphite · Porcelain · Black
Volumes
Tactile · Quiet
On this page
  1. Variants
  2. Every state, at once
  3. API
  4. Markup
  5. Accessibility
  6. How it’s built
  7. Rules
  8. Related parts
01

Variants

  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  7. 14:11:48Heat pumpDefrost cycle, 6 min
  8. 14:19:03HubTariff changed to Flux
Plain · rail only
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  7. 14:11:48Heat pumpDefrost cycle, 6 min
  8. 14:19:03HubTariff changed to Flux
Edges · a shade where there is more
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  7. 14:11:48Heat pumpDefrost cycle, 6 min
  8. 14:19:03HubTariff changed to Flux
Well · cut into the plate
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  7. 14:11:48Heat pumpDefrost cycle, 6 min
  8. 14:19:03HubTariff changed to Flux
Small rail · --sm
KitchenHeat pumpBatterySolarCarGarageWorkshopBoilerGarden
Sideways · --x
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  7. 14:11:48Heat pumpDefrost cycle, 6 min
  8. 14:19:03HubTariff changed to Flux
Both axes
02

Every state, at once

Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.

Aluminium

PartRail at restKeyboard focusWellEdges
Scroll area
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started

Graphite

PartRail at restKeyboard focusWellEdges
Scroll area
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
  1. 13:58:02HubReserve raised to 20%
  2. 13:58:40Meter 2291Missed three readings
  3. 13:59:11HubMeter 2291 is back
  4. 14:02:31BatteryFull at 13.4 kWh
  5. 14:02:32GridExporting 2.1 kW at 15p
  6. 14:07:15CarBoost charge started
03

API

NameKindValuesWhat it does
.tui-scroll-areaclasson a blockOverflow auto, contained overscroll, and the machined rail. Give it a height or max-height.
tabindex="0" · role="region" · aria-labelattributeon the areaWhat lets the keyboard scroll it, and names it. Not needed if a focusable control is inside.
--y · --xclass—Scroll one axis only; the other is clipped.
--smclass—A 10px rail in place of 14px.
--wellclass—The window is cut into the plate: the recess, with 12px inside it.
--edgesclass—A shade at the top or bottom edge only while there is more beyond it. Cover-and-shadow, no script.
--sa-rail · --sa-bgCSS property14px · var(--tui-face)The rail’s width; the colour the edge shade fades into when the area sits on something other than a panel.
::-webkit-scrollbar-track · -thumbpseudo-elementChromium, SafariThe groove and the cap. Where they are not understood the fallback below is used.
scrollbar-width · scrollbar-colorCSS propertythin · ink on wellThe fallback for browsers that cannot restyle scrollbar parts: a thin rail in the kit’s inks.
↑ ↓ · Page Up / Down · Space · Home / EndkeyboardnativeScroll the focused area, as anywhere.
04

Markup

<div class="tui-scroll-area tui-scroll-area--edges"
     tabindex="0" role="region" aria-label="Hub log"
     style="max-height: 220px">
  <ol>…a long list…</ol>
</div>

<!-- Cut into the plate, sideways only -->
<div class="tui-scroll-area tui-scroll-area--well tui-scroll-area--x"
     tabindex="0" role="region" aria-label="Circuits">
  <div style="display:flex; gap:8px; width:max-content">…</div>
</div>

Needs kit.css only, no script. How to install the kit.

05

Accessibility

  • The keyboard scrolls what it can focus: an area with no focusable control in it takes tabindex="0", and role="region" with an aria-label tells a screen reader what it is.
  • It is the browser’s own scrolling, so the wheel, touch, momentum, Page Up and Down, Space and find-in-page work as people expect; nothing is intercepted.
  • Focus shows as a 2px ring inside the edge, so a parent that clips its children cannot hide it.
  • The edge shade is a second cue that there is more; on touch screens, where the rail is hidden, it is the only one.
  • Smooth scrolling is on unless reduced motion is asked for.
06

How it’s built

The rail is the scrollbar’s own parts, dressed: the track is the kit’s recess drawn as a groove (dark under its upper wall, the lower lip lit) and the thumb is the fader cap from the fader part, a light-to-dark face, a lit top edge, a skirt inside its lower one and one ink line across the middle. A 3px transparent border keeps the cap off the groove’s walls, and background-clip: padding-box draws it inside them. Held, the cap loses its skirt. Firefox cannot restyle scrollbar parts, so it gets scrollbar-color in the kit’s inks. The edge shade is the classic cover-and-shadow pair of background layers.

07

Rules

scroll-area.rules.mdIn the brain

Give it a height, a name and a way in for the keyboard; the rail is only the dress.

4 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.

08

Fader

A continuous value along a line: a native range whose cap rides in a slot cut into the plate, with a printed scale.

Reel 342:10
Mixed0:30

Table

Rows of data with printed column labels, figures right-aligned in columns, and status in lamps with words.

Tray

A recess cut into the plate that holds other parts: keys, a selector, an empty state waiting for its first thing.

Docs
Finish
Volume