Tableview

Tableview wraps a standard HTML <table> with a polished, responsive container that handles horizontal overflow, theming, and visual behavior through CSS modifier classes alone.

Use Tableview for:

  • Data grids and admin dashboards
  • Pricing and plan comparison tables
  • Financial and analytics reports
  • User, order, and inventory listings
  • API reference and configuration tables
  • Test result and status boards
  • Any structured tabular data

FrontAlign Tableview is a pure CSS component. Every visual property is driven by --tv-* CSS custom properties defined on the wrapper, making per-table overrides possible without touching global styles.

Getting Started

Wrap any standard <table> inside a <div class="tableview">.

<div class="tableview">
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Role</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Alice</td>
        <td>Developer</td>
        <td>Active</td>
      </tr>
      <tr>
        <td>Bob</td>
        <td>Designer</td>
        <td>Away</td>
      </tr>
    </tbody>
  </table>
</div>
NameRoleStatus
AliceDeveloperActive
BobDesignerAway

No JavaScript initialization is required. Tableview is activated entirely by class names on the wrapper element.

Behavior Modifiers

Add modifier classes to the .tableview wrapper to control layout and interaction. Modifiers can be freely combined.

ClassEffect
is-stripedAlternating background on odd <tbody> rows.
is-hoverableHighlights the row under the cursor.
is-borderedAdds vertical borders between columns.
is-borderlessRemoves all row and header borders.
is-nowrapPrevents cell content from wrapping.
is-truncateTruncates overflowing text with an ellipsis. Requires fixed column widths.
is-wrapForces cell content to wrap and break at any character.
table-fixedSets table-layout: fixed for equal-width columns.
has-sticky-headerPins <thead> to the top when the table overflows vertically.

is-striped

Adds a subtle alternating background to every odd <tbody> row, making dense data easier to scan across columns.

<div class="tableview is-striped">
  <table>
    <thead>
      <tr><th>ID</th><th>Product</th><th>Price</th></tr>
    </thead>
    <tbody>
      <tr><td>1</td><td>Widget A</td><td>$9.99</td></tr>
      <tr><td>2</td><td>Widget B</td><td>$14.99</td></tr>
      <tr><td>3</td><td>Widget C</td><td>$4.99</td></tr>
      <tr><td>4</td><td>Widget D</td><td>$24.99</td></tr>
    </tbody>
  </table>
</div>
IDProductPrice
1Widget A$9.99
2Widget B$14.99
3Widget C$4.99
4Widget D$24.99

is-hoverable

Highlights the row the user's cursor is over. Useful for interactive or clickable row tables.

<div class="tableview is-hoverable">
  <table>
    <thead>
      <tr><th>Order</th><th>Customer</th><th>Total</th></tr>
    </thead>
    <tbody>
      <tr><td>#1001</td><td>Alice</td><td>$120.00</td></tr>
      <tr><td>#1002</td><td>Bob</td><td>$85.50</td></tr>
      <tr><td>#1003</td><td>Carol</td><td>$200.00</td></tr>
    </tbody>
  </table>
</div>
OrderCustomerTotal
#1001Alice$120.00
#1002Bob$85.50
#1003Carol$200.00

is-bordered

Adds a right border to every <th> and <td>, creating a full grid. The last column has no right border.

<div class="tableview is-bordered">
  <table>
    <thead>
      <tr><th>Quarter</th><th>Revenue</th><th>Expenses</th><th>Profit</th></tr>
    </thead>
    <tbody>
      <tr><td>Q1</td><td>$80,000</td><td>$50,000</td><td>$30,000</td></tr>
      <tr><td>Q2</td><td>$95,000</td><td>$60,000</td><td>$35,000</td></tr>
    </tbody>
  </table>
</div>
QuarterRevenueExpensesProfit
Q1$80,000$50,000$30,000
Q2$95,000$60,000$35,000

is-borderless

Removes all border-bottom lines from <th> and <td> elements, including the header's heavier bottom border. Produces a clean, minimal look.

<div class="tableview is-borderless">
  <table>
    <thead>
      <tr><th>Name</th><th>Email</th></tr>
    </thead>
    <tbody>
      <tr><td>Alice</td><td>alice@example.com</td></tr>
      <tr><td>Bob</td><td>bob@example.com</td></tr>
    </tbody>
  </table>
</div>
NameEmail
Alicealice@example.com
Bobbob@example.com

Combining Modifiers

All behavior modifiers can be freely combined on a single .tableview.

<!-- Striped, hoverable, and bordered -->
<div class="tableview is-striped is-hoverable is-bordered">
  <table>
    <thead>
      <tr><th>Name</th><th>Role</th><th>Department</th><th>Status</th></tr>
    </thead>
    <tbody>
      <tr><td>Alice</td><td>Engineer</td><td>Platform</td><td>Active</td></tr>
      <tr><td>Bob</td><td>Designer</td><td>Product</td><td>Active</td></tr>
      <tr><td>Carol</td><td>Manager</td><td>Ops</td><td>Away</td></tr>
    </tbody>
  </table>
</div>

<!-- Sticky header with hover highlight -->
<div class="tableview is-hoverable has-sticky-header" style="max-height: 250px; overflow-y: auto;">
  <table>...</table>
</div>

Table Themes

Apply a color theme by adding a single modifier class to the .tableview wrapper. Each theme overrides the full set of --tv-* CSS variables — background, text, borders, header, stripe, hover, and scrollbar — in one coordinated palette.

ClassBackgroundTextUse case
defaultTransparentBody textGeneral purpose
is-primaryBlue-100Blue-900Primary data, featured tables
is-successGreen-100Green-900Positive results, confirmations
is-dangerRed-100Red-900Errors, critical data
is-warningYellow-100Yellow-900Warnings, pending states
is-infoTeal-100Teal-900Informational data
is-lightLightDarkSubtle, secondary tables
is-darkDarkWhiteDark-mode style, terminal data

is-primary

<div class="tableview is-primary is-bordered">
  <table>
    <thead>
      <tr><th>Plan</th><th>Users</th><th>Price</th></tr>
    </thead>
    <tbody>
      <tr><td>Free</td><td>1</td><td>$0</td></tr>
      <tr><td>Pro</td><td>5</td><td>$29/mo</td></tr>
      <tr><td>Enterprise</td><td>Unlimited</td><td>Custom</td></tr>
    </tbody>
  </table>
</div>
PlanUsersPrice
Free1$0
Pro5$29/mo
EnterpriseUnlimitedCustom

is-success

<div class="tableview is-success is-striped">
  <table>
    <thead>
      <tr><th>Test</th><th>Result</th><th>Duration</th></tr>
    </thead>
    <tbody>
      <tr><td>Login flow</td><td>Passed</td><td>0.3s</td></tr>
      <tr><td>Checkout</td><td>Passed</td><td>1.1s</td></tr>
      <tr><td>Profile update</td><td>Passed</td><td>0.5s</td></tr>
    </tbody>
  </table>
</div>
TestResultDuration
Login flowPassed0.3s
CheckoutPassed1.1s
Profile updatePassed0.5s

is-danger

<div class="tableview is-danger is-hoverable">
  <table>
    <thead>
      <tr><th>Error</th><th>Code</th><th>Count</th></tr>
    </thead>
    <tbody>
      <tr><td>Timeout</td><td>408</td><td>12</td></tr>
      <tr><td>Not found</td><td>404</td><td>34</td></tr>
      <tr><td>Server error</td><td>500</td><td>3</td></tr>
    </tbody>
  </table>
</div>
ErrorCodeCount
Timeout40812
Not found40434
Server error5003

is-warning

<div class="tableview is-warning is-bordered">
  <table>
    <thead>
      <tr><th>Item</th><th>Stock</th><th>Threshold</th></tr>
    </thead>
    <tbody>
      <tr><td>Widget A</td><td>3</td><td>10</td></tr>
      <tr><td>Widget B</td><td>7</td><td>15</td></tr>
    </tbody>
  </table>
</div>
ItemStockThreshold
Widget A310
Widget B715

is-info

<div class="tableview is-info is-striped is-hoverable">
  <table>
    <thead>
      <tr><th>Server</th><th>Region</th><th>Uptime</th></tr>
    </thead>
    <tbody>
      <tr><td>srv-01</td><td>EU West</td><td>99.9%</td></tr>
      <tr><td>srv-02</td><td>US East</td><td>99.7%</td></tr>
      <tr><td>srv-03</td><td>AP South</td><td>99.8%</td></tr>
    </tbody>
  </table>
</div>
ServerRegionUptime
srv-01EU West99.9%
srv-02US East99.7%
srv-03AP South99.8%

is-light

<div class="tableview is-light is-bordered">
  <table>
    <thead>
      <tr><th>Setting</th><th>Default</th><th>Description</th></tr>
    </thead>
    <tbody>
      <tr><td>timeout</td><td>30s</td><td>Request timeout duration</td></tr>
      <tr><td>retries</td><td>3</td><td>Max retry attempts on failure</td></tr>
      <tr><td>cache</td><td>true</td><td>Enable response caching</td></tr>
    </tbody>
  </table>
</div>
SettingDefaultDescription
timeout30sRequest timeout duration
retries3Max retry attempts on failure
cachetrueEnable response caching

is-dark

<div class="tableview is-dark is-striped">
  <table>
    <thead>
      <tr><th>Command</th><th>Description</th></tr>
    </thead>
    <tbody>
      <tr><td>ls</td><td>List directory contents</td></tr>
      <tr><td>cd</td><td>Change directory</td></tr>
      <tr><td>pwd</td><td>Print working directory</td></tr>
      <tr><td>rm -rf</td><td>Remove files or directories recursively</td></tr>
    </tbody>
  </table>
</div>
CommandDescription
lsList directory contents
cdChange directory
pwdPrint working directory
rm -rfRemove files or directories recursively

Captions

Add a <caption> element inside <table> with either caption-top or caption-bottom to display a descriptive label above or below the data. Captions improve accessibility by giving screen readers context about the table's content.

ClassCSS propertyPosition
caption-topcaption-side: topRenders above the table header
caption-bottomcaption-side: bottomRenders below the last row
<!-- Caption above the table -->
<div class="tableview">
  <table>
    <caption class="caption-top">Monthly Sales Report — Q1 2025</caption>
    <thead>
      <tr><th>Month</th><th>Sales</th><th>Growth</th></tr>
    </thead>
    <tbody>
      <tr><td>January</td><td>$45,000</td><td>+8%</td></tr>
      <tr><td>February</td><td>$52,000</td><td>+15%</td></tr>
      <tr><td>March</td><td>$61,000</td><td>+17%</td></tr>
    </tbody>
  </table>
</div>

<!-- Caption below the table -->
<div class="tableview">
  <table>
    <caption class="caption-bottom">* All prices are in USD and exclude tax.</caption>
    <thead>
      <tr><th>Product</th><th>Price</th></tr>
    </thead>
    <tbody>
      <tr><td>Basic Plan</td><td>$9.99 *</td></tr>
      <tr><td>Pro Plan</td><td>$29.99 *</td></tr>
    </tbody>
  </table>
</div>

CSS Custom Properties

Every visual property of .tableview is controlled by --tv-* CSS variables defined on the wrapper element. Override individual properties per-table without affecting other tables on the page.

VariableDefaultDescription
--tv-bgtransparentTable and wrapper background color
--tv-textvar(--body-text)Default text color for all cells
--tv-border-colorvar(--border)Color of all row and column borders
--tv-header-bgSurface + 0.012 lightnessBackground of <thead> cells
--tv-stripe-bgBody text at 2.5% opacityBackground of odd rows when is-striped
--tv-hover-bgBody text at 5% opacityRow background on hover when is-hoverable
--tv-scroll-thumbBody text at 5% opacityScrollbar thumb color
--tv-scroll-tracktransparentScrollbar track background
--tv-radius8pxBorder radius of the wrapper

Per-table Override

Override variables inline on a specific .tableview to create a one-off custom theme without touching global CSS.

<div class="tableview is-hoverable" style="
  --tv-bg:           #f0fdf4;
  --tv-header-bg:    #dcfce7;
  --tv-border-color: #bbf7d0;
  --tv-text:         #14532d;
  --tv-hover-bg:     oklch(from var(--green-500) l c h / 0.1);
  --tv-scroll-thumb: #4ade80;
">
  <table>
    <thead>
      <tr><th>Metric</th><th>Value</th><th>Status</th></tr>
    </thead>
    <tbody>
      <tr><td>Uptime</td><td>99.99%</td><td>Healthy</td></tr>
      <tr><td>Response time</td><td>42ms</td><td>Healthy</td></tr>
      <tr><td>Error rate</td><td>0.01%</td><td>Healthy</td></tr>
    </tbody>
  </table>
</div>

Complete Example

Full-featured table with primary theme, striped rows, hover highlight, column borders, sticky header, and a caption.

<div class="tableview is-primary is-striped is-hoverable is-bordered has-sticky-header"
     style="max-height: 320px; overflow-y: auto;">
  <table>
    <caption class="caption-top">User Activity Report — June 2025</caption>
    <thead>
      <tr>
        <th>#</th>
        <th>Username</th>
        <th>Email</th>
        <th>Plan</th>
        <th>Last Active</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>1</td><td>alice</td><td>alice@example.com</td><td>Pro</td><td>Today</td><td>Active</td></tr>
      <tr><td>2</td><td>bob</td><td>bob@example.com</td><td>Free</td><td>Yesterday</td><td>Active</td></tr>
      <tr><td>3</td><td>carol</td><td>carol@example.com</td><td>Enterprise</td><td>2 days ago</td><td>Active</td></tr>
      <tr><td>4</td><td>dave</td><td>dave@example.com</td><td>Pro</td><td>5 days ago</td><td>Inactive</td></tr>
      <tr><td>5</td><td>eve</td><td>eve@example.com</td><td>Free</td><td>1 week ago</td><td>Inactive</td></tr>
      <tr><td>6</td><td>frank</td><td>frank@example.com</td><td>Pro</td><td>Today</td><td>Active</td></tr>
    </tbody>
  </table>
</div>

Accessibility

Tableview is a pure CSS wrapper around a native <table> element, so full semantic accessibility is inherited automatically.

Recommended practices:

  • Always use <thead> and <th> for header cells so screen readers can associate column labels with data cells.
  • Use <caption> with caption-top or caption-bottom to give the table a descriptive title that screen readers announce before the data.
  • Add scope="col" or scope="row" to <th> elements in complex tables with multiple header levels.
  • Do not use Tableview for layout purposes — it is for tabular data only.
  • When using has-sticky-header, ensure the constrained height is large enough to show at least several rows so the sticky effect is meaningful.

Class Reference

ClassApplies toRole
.tableviewWrapper <div>Scroll container, border, radius, CSS variable scope.
.is-stripedWrapperOdd-row alternating background.
.is-hoverableWrapperRow background on cursor hover.
.is-borderedWrapperVertical column dividers.
.is-borderlessWrapperRemoves all row and header borders.
.is-nowrapWrapperPrevents cell content from wrapping.
.is-truncateWrapperTruncates overflowing text with ellipsis.
.is-wrapWrapperForces content wrap at any character.
.table-fixedWrapperFixed table-layout for equal-width columns.
.has-sticky-headerWrapperPins <thead> on vertical scroll.
.is-primaryWrapperBlue coordinated theme.
.is-successWrapperGreen coordinated theme.
.is-dangerWrapperRed coordinated theme.
.is-warningWrapperYellow coordinated theme.
.is-infoWrapperTeal coordinated theme.
.is-lightWrapperLight neutral theme.
.is-darkWrapperDark inverted theme.
.caption-top<caption>Positions caption above the header row.
.caption-bottom<caption>Positions caption below the last row.

Notes

  • Tableview requires no JavaScript — it is activated entirely by class names.
  • All --tv-* variables are scoped to the .tableview wrapper, so overriding them inline affects only that table instance.
  • is-truncate requires table-fixed and explicit column widths to work correctly — without fixed layout the browser may still expand cells to fit content.
  • has-sticky-header requires overflow-y: auto and a constrained max-height on the wrapper — without them position: sticky has no scroll container to pin against.
  • Color themes and behavior modifiers are independent — any theme class can be combined with any modifier class.
  • The default table-layout: auto lets the browser size columns to fit content. Use table-fixed when you need precise column width control.

FrontAlign