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>
| Name | Role | Status |
|---|---|---|
| Alice | Developer | Active |
| Bob | Designer | Away |
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.
| Class | Effect |
|---|---|
is-striped | Alternating background on odd <tbody> rows. |
is-hoverable | Highlights the row under the cursor. |
is-bordered | Adds vertical borders between columns. |
is-borderless | Removes all row and header borders. |
is-nowrap | Prevents cell content from wrapping. |
is-truncate | Truncates overflowing text with an ellipsis. Requires fixed column widths. |
is-wrap | Forces cell content to wrap and break at any character. |
table-fixed | Sets table-layout: fixed for equal-width columns. |
has-sticky-header | Pins <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>
| ID | Product | Price |
|---|---|---|
| 1 | Widget A | $9.99 |
| 2 | Widget B | $14.99 |
| 3 | Widget C | $4.99 |
| 4 | Widget 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>
| Order | Customer | Total |
|---|---|---|
| #1001 | Alice | $120.00 |
| #1002 | Bob | $85.50 |
| #1003 | Carol | $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>
| Quarter | Revenue | Expenses | Profit |
|---|---|---|---|
| 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>
| Name | |
|---|---|
| Alice | alice@example.com |
| Bob | bob@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.
| Class | Background | Text | Use case |
|---|---|---|---|
| default | Transparent | Body text | General purpose |
is-primary | Blue-100 | Blue-900 | Primary data, featured tables |
is-success | Green-100 | Green-900 | Positive results, confirmations |
is-danger | Red-100 | Red-900 | Errors, critical data |
is-warning | Yellow-100 | Yellow-900 | Warnings, pending states |
is-info | Teal-100 | Teal-900 | Informational data |
is-light | Light | Dark | Subtle, secondary tables |
is-dark | Dark | White | Dark-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>
| Plan | Users | Price |
|---|---|---|
| Free | 1 | $0 |
| Pro | 5 | $29/mo |
| Enterprise | Unlimited | Custom |
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>
| Test | Result | Duration |
|---|---|---|
| Login flow | Passed | 0.3s |
| Checkout | Passed | 1.1s |
| Profile update | Passed | 0.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>
| Error | Code | Count |
|---|---|---|
| Timeout | 408 | 12 |
| Not found | 404 | 34 |
| Server error | 500 | 3 |
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>
| Item | Stock | Threshold |
|---|---|---|
| Widget A | 3 | 10 |
| Widget B | 7 | 15 |
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>
| Server | Region | Uptime |
|---|---|---|
| srv-01 | EU West | 99.9% |
| srv-02 | US East | 99.7% |
| srv-03 | AP South | 99.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>
| Setting | Default | Description |
|---|---|---|
| timeout | 30s | Request timeout duration |
| retries | 3 | Max retry attempts on failure |
| cache | true | Enable 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>
| Command | Description |
|---|---|
| ls | List directory contents |
| cd | Change directory |
| pwd | Print working directory |
| rm -rf | Remove 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.
| Class | CSS property | Position |
|---|---|---|
caption-top | caption-side: top | Renders above the table header |
caption-bottom | caption-side: bottom | Renders 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.
| Variable | Default | Description |
|---|---|---|
--tv-bg | transparent | Table and wrapper background color |
--tv-text | var(--body-text) | Default text color for all cells |
--tv-border-color | var(--border) | Color of all row and column borders |
--tv-header-bg | Surface + 0.012 lightness | Background of <thead> cells |
--tv-stripe-bg | Body text at 2.5% opacity | Background of odd rows when is-striped |
--tv-hover-bg | Body text at 5% opacity | Row background on hover when is-hoverable |
--tv-scroll-thumb | Body text at 5% opacity | Scrollbar thumb color |
--tv-scroll-track | transparent | Scrollbar track background |
--tv-radius | 8px | Border 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>withcaption-toporcaption-bottomto give the table a descriptive title that screen readers announce before the data. - Add
scope="col"orscope="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
| Class | Applies to | Role |
|---|---|---|
.tableview | Wrapper <div> | Scroll container, border, radius, CSS variable scope. |
.is-striped | Wrapper | Odd-row alternating background. |
.is-hoverable | Wrapper | Row background on cursor hover. |
.is-bordered | Wrapper | Vertical column dividers. |
.is-borderless | Wrapper | Removes all row and header borders. |
.is-nowrap | Wrapper | Prevents cell content from wrapping. |
.is-truncate | Wrapper | Truncates overflowing text with ellipsis. |
.is-wrap | Wrapper | Forces content wrap at any character. |
.table-fixed | Wrapper | Fixed table-layout for equal-width columns. |
.has-sticky-header | Wrapper | Pins <thead> on vertical scroll. |
.is-primary | Wrapper | Blue coordinated theme. |
.is-success | Wrapper | Green coordinated theme. |
.is-danger | Wrapper | Red coordinated theme. |
.is-warning | Wrapper | Yellow coordinated theme. |
.is-info | Wrapper | Teal coordinated theme. |
.is-light | Wrapper | Light neutral theme. |
.is-dark | Wrapper | Dark 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.tableviewwrapper, so overriding them inline affects only that table instance. is-truncaterequirestable-fixedand explicit column widths to work correctly — without fixed layout the browser may still expand cells to fit content.has-sticky-headerrequiresoverflow-y: autoand a constrainedmax-heighton the wrapper — without themposition: stickyhas 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: autolets the browser size columns to fit content. Usetable-fixedwhen you need precise column width control.