A table you can build from data or write out by hand, with stripes, hover rows and border options.
About
Pass headers and data and the Table builds the rows for you, or write THead, TBody, TR, TH and TD out by hand. The two styles mix freely, and the output is always wrapped in a horizontally scrollable container.
Example
There are several ways to build a table. For example:
- Using data
- Using snippet
- Manually using the components
Setup
At first import the relevant components of the table.
<script>
import { Table, THead, TBody, TR, TH, TD } from "theui-svelte";
</script>Example: Using Props
The Table component allows you to generate tables dynamically using data. This approach is useful when you have structured data and want to render it efficiently without manually defining each row and column. This method ensures your table remains dynamic and adaptable to different datasets.
Pass the headers, data, and keys as props to the Table component.
headers: string[]- An array of column headers.data: object[]- An array of objects representing table rows.keys: string[]- An array of keys that map data fields to columns.
Cell values passed this way are rendered as plain text, so HTML inside them is not rendered. A key that is missing from a row renders an empty cell. To add custom markup, use the components as shown in the next example.
| Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<script>
let headers = ["Heading 1", "Heading 2", "Heading 3", "Heading 4"];
let data = [
{item1: "Data 11", item2: "Data 12", item3: "Data 13", item4: "Data 14"},
{item1: "Data 21", item2: "Data 22", item3: "Data 23", item4: "Data 24"},
{item1: "Data 31", item2: "Data 23", item3: "Data 33", item4: "Data 43"},
];
let keys = ["item1", "item2", "item3", "item4"];
</script>
<!-- Option 1 -->
<Table {headers} {data} {keys} />
<!-- Option 2 -->
<Table>
<THead {headers} />
<TBody {data} {keys} />
</Table>
<!-- Option 3 -->
<Table {headers}>
<TBody>
{#each data as d}
<TR data={d} {keys} />
{/each}
</TBody>
</Table>Example: Using Components
Instead of props or dynamically looping through the data, the table content is written manually using the THead, TBody, TR, TH and TD components.
<THead>- Contains the header row.<TBody>- Contains the table rows.<TR>- Represents a table row. AddtableHeader={true}to the header row so it gets thetrHeadClassesstyles. When aTRrenders its cells from thedataprop,tableHeaderalso makes it render<th>cells instead of<td>.<TH>- Represents a header cell.<TD>- Represents a table data containing the actual data.
| Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<Table>
<THead>
<TR tableHeader={true}>
<TH>Heading 1</TH>
<TH>Heading 2</TH>
<TH>Heading 3</TH>
<TH>Heading 4</TH>
</TR>
</THead>
<TBody>
<TR>
<TD>Data 11</TD>
<TD>Data 12</TD>
<TD>Data 13</TD>
<TD>Data 14</TD>
</TR>
...
...
</TBody>
</Table>Custom Header
If you need custom headers or anything other than text in the header just put your custom items in the TH component. For example:
| Sort | Sort |
|---|
<Table>
<THead>
<TR>
<TH class="items-center gap-2">
Sort
<Svg class="inline">
<path d="M3.5 12.5a.5.5 0 0 ... 0 1h1a.5.5 0 0 0 0-1z"/>
</Svg>
</TH>
<TH class="items-center gap-2">
Sort
<Svg class="inline">
<path d="M3.5 2.5a.5.5 0 0 0-1 ... 1h1a.5.5 0 0 0 0-1z"/>
</Svg>
</TH>
</TR>
</THead>
</Table>Table Border
The border prop controls where borders appear in the table. By default, it is set to "both". Setting it to "x" adds borders only between columns, while "y" applies borders only between rows. The default option, "both", adds borders between both rows and columns, and "none" removes all borders. This prop allows you to customize the table's appearance based on your design preferences.
border="x" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
border="y" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
border="none" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<Table {headers} {data} {keys} border="x" />
<Table {headers} {data} {keys} border="y" />
<Table {headers} {data} {keys} border="none" />Table Spacing
The space prop adjusts the cell padding to control the overall table spacing, affecting how compact or spacious the table appears.
"compact"- Reduces padding for a denser layout, making the table more space-efficient."default"(Default value) - Uses the standard padding, providing a balanced look."comfortable"- Increases padding for a more spacious and readable layout.
space="compact" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
space="comfortable" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<Table {headers} {data} {keys} space="compact" />
<Table {headers} {data} {keys} space="comfortable" />Stripe Rows
The stripe prop adds alternating background colors to table rows, improving readability and visual distinction between rows. By default, this feature is disabled (undefined), meaning all rows have the same background.
"even"- Applies striping to even-numbered rows, making them visually distinct from odd rows."odd"Applies striping to odd-numbered rows, enhancing readability by differentiating them from even rows.- Custom class names - You can specify a class name instead of predefined values to apply custom styling. This allows full control over the appearance of striped rows, making it easy to match your design needs.
stripe="even" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
stripe="odd" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
stripe="<CUSTOM CLASSES>" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
stripe="<CUSTOM CLASSES>" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<!-- Striped even rows -->
<Table {headers} {data} {keys} stripe="even" />
<!-- Striped odd rows -->
<Table {headers} {data} {keys} stripe="odd" />
<!-- Striped even rows with custom classes -->
<Table {headers} {data} {keys} stripe="even:bg-green-100 dark:even:bg-green-900" />
<!-- Striped odd rows with custom classes -->
<Table {headers} {data} {keys} stripe="odd:bg-green-100 dark:odd:bg-green-900" />Hoverable Rows
The hover prop enables a visual highlight effect when users hover over table rows. By default, this feature is disabled (undefined), meaning no hover effect is applied.
true- When set totrue, the row background color changes on hover, improving user experience and readability.- Custom class names - Instead of using the default hover effect, you can pass a custom class to define your own hover styles, allowing for more design flexibility.
Use the animationSpeed prop to control how fast the hover color changes. Available values are "none", "slower", "slow", "normal" (default), "fast" and "faster".
hover={true} | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
hover="<CUSTOM CLASSES>" | Heading 1 | Heading 2 | Heading 3 | Heading 4 |
|---|---|---|---|
| Data 11 | Data 12 | Data 13 | Data 14 |
| Data 21 | Data 22 | Data 23 | Data 24 |
| Data 31 | Data 23 | Data 33 | Data 43 |
<!-- Hoverable rows -->
<Table {headers} {data} {keys} hover={true} />
<!-- Hoverable rows with custom classes -->
<Table {headers} {data} {keys} hover="hover:bg-red-100" />
<!-- Slower hover transition -->
<Table {headers} {data} {keys} hover={true} animationSpeed="slower" />Customization
You can use the following props to customize the table's appearance, allowing you to style the table and its elements as needed.
borderColor- the border color for the table. The default is"border-gray-200/80 dark:border-gray-800/80", which reads in both light and dark mode. Override it with any Tailwind border color class.trHeadClasses- Adds custom classes to the table header row ((<tr> inside <thead>)). This allows you to style the header separately, such as applying background colors, text styles, or spacing adjustments.trClasses- Applies custom classes to all table body rows (<tr> inside <tbody>). Use this to control row styling, such as padding, text alignment, or hover effects.thClasses- Adds custom classes to all table header cells (<th>), enabling control over the header text size, padding, alignment, or other styles.tdClasses- Adds custom classes to all table cells (<td>), enabling precise control over text size, padding, alignment, or other styles.
class attribute with any table related component to add your custom CSS classes. Accessibility
A data table is read cell by cell, so a screen reader has to know which header each cell belongs to. Build the table from headers and data and that is handled: every header cell is written as <th scope="col">.
Writing the rows yourself works the same way, because TH now sets scope="col" on its own. Change it to scope="row" on a header cell that names its row, such as the first cell of each line in a comparison table.
<TR>
<TH scope="row">Starter</TH>
<TD>$9</TD>
<TD>3 projects</TD>
</TR>Give the table a name with ariaLabel, or write a <caption> as the first thing inside it. Screen readers list the tables on a page, and an unnamed one is listed as nothing but "table".
<Table ariaLabel="Pricing plans" {headers} {data} />A table wider than its container scrolls sideways. That box is a tab stop while it overflows, so people who do not use a mouse can scroll it with the arrow keys, and it is announced as a region using the name from ariaLabel. When the table fits, the tab stop disappears again, so it never adds a stop for nothing.
Two things are still yours to get right: keep the header row in a THead rather than styling the first body row to look like one, and do not use a table for layout, since everything in it is announced as data.