Source: src/styles/parts/tables.scs — and controls::table /
controls::table-data for a table inside a shadow root.
Two kinds, and they are not the same object. A <table> is a table inside a page or a
document — read, occasionally sorted. A table.data is the data grid of an application
— scanned, filtered, selected, paginated. Neither uses zebra striping: hairlines separate the rows
and the hover ground tracks the eye, because zebra fights the status colours a data row carries.
The document table
Invoices, Q3
Reference
Client
Status
Amount
INV-0146
Hydra Agency
Paid
1 250,00
INV-0147
Oviepro
Late
860,00
INV-0148
Lorem SAS
Draft
3 400,00
Total
5 510,00
Framework
mmo.core
the php framework
mmo.client
the client library
Tooling
mmo.doc
the documentation generator
Variants
Rail width
232px
Control height
34px
Content measure
1180px
Token
Light
Dark
$color.bg
#F1F3F7
#0D121B
$color.surface
#FFFFFF
#161C27
$color.text
#161C27
#F1F3F7
Template
Shape
admin
rail, breadcrumb, page tabs, content, side panel, status bar
landing
sticky translucent header, hero, sections, large footer
The header stays put while the body scrolls — the container is what scrolls, not the table, which
is what .table-wrap is for. Rows hover, and a selected row takes the brand's soft ground,
from either .selected or aria-selected="true".
Client
Contact
Status
Amount
HAHydra AgencyParis
marc@hydra-agency.com
Active
1 250,00
OVOvieproLyon
contact@oviepro.fr
Pending
860,00
LSLorem SASLille
hello@lorem.example
Blocked
3 400,00
IPIpsum SARLMarseille
contact@ipsum.example
Trial
120,00
That header sticks on its own: table.data thead th is already
position: sticky. Any other table — or a column rather than a row — asks for it
with the .sticky classes,
which are the same fragment (lib::sticky) an element inlines inside its own shadow root:
Reference
Client
Contact
City
Amount
INV-0146
Hydra Agency
marc@hydra-agency.com
Paris
1 250,00
INV-0147
Oviepro
contact@oviepro.fr
Lyon
860,00
INV-0148
Lorem SAS
hello@lorem.example
Lille
3 400,00
INV-0149
Ipsum SARL
contact@ipsum.example
Marseille
120,00
INV-0150
Dolor SA
hello@dolor.example
Nantes
640,00
A sticky row needs a ground on its cellsUnder border-collapse: collapse a <thead>'s own background does not
paint, so the rows would scroll straight through it. table.data paints its header cells
already; a plain table's do not, which is why the specimen above puts .sticky on the cells
as well as on the row.
The pieces of that grid, one by one:
th[data-sort] says the column is sortable; data-sort="asc" /
"desc" draws which way it is sorting.
td.number, th.number and td.currency align right in a
monospaced tabular figure, so magnitudes are comparable down the column.
A checkbox column and a .actions column never grow.
.who is the identity cell: an avatar, a name and the one .sub detail that
disambiguates it.
Id
Event
When
Duration
a8f1
compile
2026-09-18 14:31
128 ms
a8f2
render
2026-09-18 14:31
12 ms
a8f3
flush
2026-09-18 14:31
3 ms
What frames a grid
.table-tools above it, .table-foot under it, both hairlined against the grid;
.table-wrap is the scroller the sticky header needs. In a .panel the three add
up to the standard screen of an application.
Reference
Client
Amount
INV-0146
Hydra Agency
1 250,00
INV-0147
Oviepro
860,00
2 of 148
No invoice yet
Issue one from a quote, or import a batch.
Below 720px a data grid cannot stack: .table-wrap scrolls sideways in its own container
instead. For a grid driven by data rather than written by hand, see
<mmo-table>.