Data Table

The visible companion to the charts — a native, accessible <table> with numeric alignment, zebra rows, a totals footer, and trend cells. No JavaScript. Interactivity comes from composing with the filter primitive (below); sort and pagination are server-driven.

Basic + totals + trend

Revenue by product line (FY25)
Product Revenue Units YoY
Atlas Pro $1,240,000 3,100 +8.2%
Beacon $980,500 5,420 -3.1%
Cirrus $2,015,750 1,870 +14.6%
Delta Lite $455,000 9,030 0.0%
Total $4,691,250 19,420

Sticky header (scroll the box)

Month Visitors Signups
January42,3101,204
February39,8801,150
March51,4201,690
April48,9001,512
May55,0301,820
June60,1102,005
July58,6401,944

Sortable column (server-driven)

City Population
Tokyo37,400,000
Delhi32,900,000
Shanghai29,200,000

The column with aria-sort="descending" shows a ↓ glyph; its link points at the server's sort URL. CSS never reorders rows (no JS) — the server renders them in order.

Filterable rows (composed with .casca-filter)

Item Category MRR
Edge NodeHardware$12,400
Dashboard ProSoftware$38,900
OnboardingServices$9,150
API TierSoftware$21,300
Sensor KitHardware$6,720

Uncheck a category to hide its rows (the table reflows). Pure CSS via :has(); the rows carry data-filter.

Selectable rows (no-JS, submits with the form)

Select Item MRR
Atlas Pro $1,240
Beacon $980
Cirrus $2,016
Delta Lite $455

Checked rows highlight (brand tint, distinct from hover) and submit as rows=<value>. Select-all and a live count need JS or a server round-trip — out of scope for the CSS primitive.

Markup

<table class="casca-table">
  <thead>
    <tr><th scope="col">Product</th><th scope="col" class="casca-table-num">YoY</th></tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Atlas</th>
      <td class="casca-table-num" data-trend="up">+8.2%</td>
    </tr>
    <!-- data-trend = up | down | flat; .casca-table-num right-aligns -->
  </tbody>
</table>