Tables

Licences · Department of Planning
ModulesStatusActions
Layla HaddadDepartment of PlanningShaheen, Mai42026-10-12Active
Ahmed RahmanDepartment of PlanningMai22026-10-13Active
Sara KhalilMinistry of WaterAll modules62026-10-09Expiring
Mariam SaeedCentral ArchiveMai, Emails22026-09-30Active
Noura ObaidCentral ArchiveMai12026-08-21Revoked
1 selected · 5 of 128 users

Tables are for comparing

Use a table when people need to compare values across rows and columns. If they only need to read items, use a list; if they need one number, use a big number.

Anatomy

Part / stateValueToken
Container1px Steel 20 border, 12px radius, raised surface; scrolls horizontally inside, never the page--n-border-ui, --n-radius-md
CaptionDisplay Medium 15px, above the table, states what it shows
Header rowSteel 05 fill (Midnight 90 dark), Text SemiBold 12px, caption colour, +0.03em, no wrap, sticky--n-table-header
Body cellText 14px, 11px × 16px padding, 44px row--n-size-table-row
Row divider1px Steel 20 horizontal rule; no vertical rules by default--n-border-ui
Row headerFirst column as <th scope="row">, Medium, heading colour
FooterTotals: SemiBold, 2px top rule, subtle fill. Pagination bar below the table

Borders

StyleBordersUse
DefaultOuter frame + horizontal row rules onlyAlmost everything: lists of records, settings, logs
GridHorizontal and vertical rulesComparison tables, merged headers, spreadsheet-like data
ZebraAlternate rows on Steel 05 instead of rulesVery wide numeric tables, where the eye must follow a row
BorderlessNo frame, rules onlyTables inside cards or documents

Never combine zebra and grid. Never use heavy (2px+) borders except the totals rule.

Alignment

  • Text: left (right in Arabic). Header aligns with its column's content.
  • Numbers, money, dates in ISO, durations: right, with tabular figures (font-variant-numeric: tabular-nums), so digits line up.
  • Status badges and icons: left, after text columns. Actions: last column, right.
  • Units go in the header (“Latency (ms)”), not in every cell.
  • Truncate long text with an ellipsis and a tooltip; never wrap IDs.

Merged and highlighted cells

Grouped headers, row spans and highlighted cells

RegimeRequests (thousands)Median latency (ms)
SepOctSepOct
On-premises334362690640
1214610602
Residency-gated131142—720
Cloud-permitted7270590605
Total549588——
Cell treatmentLookMeans
Grouped header (colspan)Centred, spans its group, rule belowColumns that belong together
Row spanTop-aligned, subtle fill, rule on the rightA value shared by several rows
HighlightDawn tint, SemiBoldThe value the reader should notice (best, changed, latest). One or two per table
AI value1.5px Oasis inset outline + tooltipComputed, forecast or suggested by AI
Error / missingStatus-danger text on danger tint, “—” for missingFailed, invalid or unavailable
Selected rowAction tint + 3px leading edgeRows chosen with checkboxes

Merge cells only in headers and for genuinely shared values. Never merge body cells to create layout; screen readers must still be able to read every cell with its headers (scope, headers).

Row states and interaction

  • Hover: a faint tint across the row. Click target: the whole row only when it opens one thing; otherwise a link in the first column.
  • Selection: checkbox column on the leading edge; header checkbox selects the page, with an indeterminate state; a bulk-action bar replaces the footer while rows are selected.
  • Sorting: click the header; arrow shows the direction; aria-sort on the <th>. One sort at a time by default.
  • Expandable rows: chevron in the first cell; details open below in an inset panel.
  • Inline edit: on double-click or an edit icon; save on Enter, cancel on Esc.
  • Sticky header always; sticky first column when the table scrolls horizontally.

Density

Density and zebra

Compact · 32px rows

EventTime
Licence check09:40:12
Model request09:40:15
Licence check09:55:12

Zebra · comfortable

ModelTokens
Llama 70B1,204,880
Qwen 32B688,102
Claude92,400

Empty, loading and error states

Empty and loading

UserStatus

No users match “Ministry of Energy”.

UserStatus
  • Loading: keep the header; show 3–5 skeleton rows with the real column widths.
  • Empty: explain why and offer the next action (clear filters, add the first item).
  • Error: keep the header, show an inline alert in the body with Retry.

Responsive tables

ViewportBehaviour
≥ 960pxFull table
640–959pxHide lower-priority columns (marked in the design); keep the row header, status and actions
< 640pxEither horizontal scroll with a sticky first column and an edge fade, or stack each row as a card of label–value pairs. Choose cards for records, scroll for numeric comparison

Tables in documents and slides

  • Use the Word template's table style or the hub's table style: header in caption colour capitals 12px, horizontal rules, no fills except totals.
  • Slides: at most 6 rows × 5 columns at 18pt or larger; otherwise use a chart or an appendix.
  • Arabic tables mirror the column order: the row header column is on the right.

Code

<div class="n-table-wrap">
  <table class="n-table">               <!-- n-table--grid | --zebra | --compact | --relaxed -->
    <caption>Licences</caption>
    <thead><tr><th scope="col" aria-sort="ascending"><button class="sort">User</button></th><th scope="col" class="num">Models</th></tr></thead>
    <tbody>
      <tr class="is-selected"><th scope="row">Layla Haddad</th><td class="num">4</td></tr>
      <tr><th scope="row">Sara Khalil</th><td class="num is-highlight">6</td></tr>
    </tbody>
  </table>
</div>

<!-- Tailwind -->
<th class="sticky top-0 bg-n-table-header text-n-caption text-xs font-semibold tracking-wide whitespace-nowrap px-4 py-3 text-left border-b border-n-border-ui">
<td class="px-4 py-3 border-b border-n-border-ui text-right tabular-nums">

Dos and don'ts

Do

  • Write a caption that says what the table shows.
  • Right-align numbers with tabular figures.
  • Keep the header sticky and the first column as row headers.
  • Highlight at most one or two cells.

Don't

  • Use tables for page layout.
  • Add vertical rules and zebra stripes together.
  • Squeeze columns until text wraps letter by letter: scroll or stack instead.
  • Merge body cells for visual effect.

Last updated on 14 October 2026