Table
Element that displays tabular data in a structured format of rows and columns.
| Class name | Type | |
|---|---|---|
.prs-table-container |
Component | Container |
.prs-table |
Component | For <table> |
.prs-cell-actions |
Component | Header cell actions container |
.prs-cell-info |
Component | Info tooltip container |
.prs-cell-sort |
Component | Sorting container |
.prs-table-bordered |
Modifier | Add divider lines |
.prs-table-striped |
Modifier | Even/odd highlight |
.prs-table-compact |
Modifier | Less padding |
.prs-table-pin-rows |
Modifier | Sticky <thead> and <tfoot> |
.prs-table-pin-cols |
Modifier | Sticky <th> columns |
.prs-cell-sort |
Modifier | Sortable |
.prs-cell-name |
Modifier | Name/email |
.prs-cell-stacked |
Modifier | Stacked content |
.prs-cell-end |
Modifier | Justify end/right |
-
Default
Here's a decent starting point with a little help from Alpine.js (just to toggle the asd/desc caret direction).
<div x-data="{ sort: 'asc' }" class="w-screen max-w-lg"> <!-- <- this is just for demo purposes --> <div class="prs-table-container"> <table class="prs-table prs-table-bordered"> <thead> <tr> <th class="prs-cell-stacked"> <span class="prs-cell-actions"> <span>Header</span> <a x-tooltip="'More info'" @click.prevent href="#tooltip" class="prs-cell-info" aria-label="More info"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" role="img"><use href="/_assets/prs-icons.svg#content-type-info-outline" /></svg></a> <a @click.prevent="sort = (sort === 'asc' ? 'desc' : 'asc')" :aria-label="'Sorted '+ sort" :class="sort" class="prs-cell-sort" href="#sort" ><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" role="img"><use href="/_assets/prs-icons.svg#caret-down" /></svg></a> </span> <strong>Sub label</strong> </th> <th>Header</th> <th class="prs-cell-stacked prs-cell-end"> <span>Header</span> <strong>Sub label</strong> </th> </tr> </thead> <tbody> <tr> <td class="prs-cell-stacked"> <span>Cell</span> <em>Some data</em> </td> <td>Cell</td> <td class="prs-cell-end">Cell</td> </tr> <tr> <td class="prs-cell-stacked"> <span>Cell</span> <em>Some data</em> </td> <td>Cell</td> <td class="prs-cell-end">Cell</td> </tr> <tr> <td class="prs-cell-name prs-cell-stacked"> <span>First <strong>Last</strong></span> <em>me@domin.ext</em> </td> <td>Cell</td> <td class="prs-cell-end">Cell</td> </tr> <tr> <td class="prs-cell-stacked"> <span>Cell</span> <em>Some data</em> </td> <td>Cell</td> <td class="prs-cell-end">Cell</td> </tr> <tr> <td class="prs-cell-stacked"> <span>Cell</span> <em>Some data</em> </td> <td>Cell</td> <td class="prs-cell-end">Cell</td> </tr> </tbody> <tfoot> <tr> <th class="prs-cell-stacked"> <span>Header</span> <strong>Sub label</strong> </th> <th>Header</th> <th class="prs-cell-stacked prs-cell-end"> <span>Header</span> <strong>Sub label</strong> </th> </tr> </tfoot> </table> </div> </div> -
Compact
Less padding.
<div class="w-screen max-w-lg"> <!-- <- this is just for demo purposes --> <div class="prs-table-container"> <table class="prs-table prs-table-bordered prs-table-compact"> <thead> <tr><th>Header</th><th>Header</th><th>Header</th></tr> </thead> <tbody> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> </tbody> </table> </div> </div> -
Striped
Event rows highlighted.
<div class="w-screen max-w-lg"> <!-- <- this is just for demo purposes --> <div class="prs-table-container"> <table class="prs-table prs-table-bordered prs-table-striped"> <thead> <tr><th>Header</th><th>Header</th><th>Header</th></tr> </thead> <tbody> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> <tr><td>Cell</td><td>Cell</td><td>Cell</td></tr> </tbody> </table> </div> </div> -
Pinned Rows
Scroll the table vertically.
<div class="w-screen max-w-xs"> <!-- <- this is just for demo purposes --> <div class="prs-table-container" style="height: 18rem;"> <!-- <- give the container an explicit height --> <table class="prs-table prs-table-bordered prs-table-pin-rows"> <thead><tr><th>A</th></tr></thead> <tbody> <tr><td>Ant-Man</td></tr> <tr><td>Aquaman</td></tr> <tr><td>Asterix</td></tr> <tr><td>The Atom</td></tr> <tr><td>The Avengers</td></tr> </tbody> <thead><tr><th>B</th></tr></thead> <tbody> <tr><td>Batgirl</td></tr> <tr><td>Batman</td></tr> <tr><td>Batwoman</td></tr> <tr><td>Black Canary</td></tr> <tr><td>Black Panther</td></tr> </tbody> <thead><tr><th>C</th></tr></thead> <tbody> <tr><td>Captain America</td></tr> <tr><td>Captain Marvel</td></tr> <tr><td>Catwoman</td></tr> <tr><td>Conan the Barbarian</td></tr> </tbody> <thead><tr><th>D</th></tr></thead> <tbody> <tr><td>Daredevil</td></tr> <tr><td>The Defenders</td></tr> <tr><td>Doc Savage</td></tr> <tr><td>Doctor Strange</td></tr> </tbody> <thead><tr><th>E</th></tr></thead> <tbody> <tr><td>Elektra</td></tr> </tbody> <thead><tr><th>F</th></tr></thead> <tbody> <tr><td>Fantastic Four</td></tr> </tbody> <thead><tr><th>G</th></tr></thead> <tbody> <tr><td>Ghost Rider</td></tr> <tr><td>Green Arrow</td></tr> <tr><td>Green Lantern</td></tr> <tr><td>Guardians of the Galaxy</td></tr> </tbody> <thead><tr><th>H</th></tr></thead> <tbody> <tr><td>Hawkeye</td></tr> <tr><td>Hellboy</td></tr> <tr><td>Incredible Hulk</td></tr> </tbody> <thead><tr><th>I</th></tr></thead> <tbody> <tr><td>Iron Fist</td></tr> <tr><td>Iron Man</td></tr> </tbody> <thead><tr><th>M</th></tr></thead> <tbody> <tr><td>Marvelman</td></tr> </tbody> <thead><tr><th>R</th></tr></thead> <tbody> <tr><td>Robin</td></tr> <tr><td>The Rocketeer</td></tr> </tbody> <thead><tr><th>S</th></tr></thead> <tbody> <tr><td>The Shadow</td></tr> <tr><td>Spider-Man</td></tr> <tr><td>Sub-Mariner</td></tr> <tr><td>Supergirl</td></tr> <tr><td>Superman</td></tr> </tbody> <thead><tr><th>T</th></tr></thead> <tbody> <tr><td>Teenage Mutant Ninja Turtles</td></tr> <tr><td>Thor</td></tr> </tbody> <thead><tr><th>W</th></tr></thead> <tbody> <tr><td>The Wasp</td></tr> <tr><td>Watchmen</td></tr> <tr><td>Wolverine</td></tr> <tr><td>Wonder Woman</td></tr> </tbody> <thead><tr><th>X</th></tr></thead> <tbody> <tr><td>X-Men</td></tr> </tbody> <thead><tr><th>Z</th></tr></thead> <tbody> <tr><td>Zatanna</td></tr> <tr><td>Zatara</td></tr> </tbody> </table> </div> </div> -
All Modifiers
Compact, Bordered, Striped, Pinned rows, Pinned columns. Scroll the table in any direction to see the pinned cells.
<div class="w-screen max-w-md"> <!-- <- this is just for demo purposes --> <div class="prs-table-container h-72"> <table class="prs-table prs-table-compact prs-table-bordered prs-table-striped prs-table-pin-cols prs-table-pin-rows"> <thead><tr><th></th><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><th></th></tr></thead> <tbody> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> <tr><th>Pinned</th><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><td>Cell</td><th>Pinned</th></tr> </tbody> <tfoot><tr><th></th><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><td>Pinned</td><th></th></tr></tfoot> </table> </div> </div>
CSS
Full Library
Component Only
.prs-table-container {
font-size: 1rem;
line-height: 1.5rem;
overflow-x: auto;
}
.prs-table {
width: 100%;
font-size: inherit;
line-height: inherit;
:where(th, td) {
padding: 1rem;
color: var(--prs-c-gray-800);
vertical-align: middle;
}
&.prs-table-compact {
:where(th, td) {
padding: 0.5rem;
}
}
:where(th, thead td, tfoot td) {
color: var(--prs-c-gray-600);
font-weight: 600;
text-align: start;
vertical-align: bottom;
position: relative;
}
:where(tfoot th) {
vertical-align: top;
}
&.prs-table-bordered {
:where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) {
border-bottom: 1px solid var(--prs-c-gray-300);
}
:where(tfoot tr:last-child) {
border-top: 1px solid var(--prs-c-gray-300);
}
}
&.prs-table-striped {
tbody tr:nth-child(2n) {
background-color: var(--prs-c-gray-100);
}
tbody tr:nth-child(2n) :where(.prs-table-pin-cols tr th) {
background-color: var(--prs-c-gray-100);
}
}
:where(.prs-table-pin-rows thead tr, .prs-table-pin-rows tfoot tr) {
background: var(--prs-c-white);
position: sticky;
top: 0;
z-index: 1;
}
:where(.prs-table-pin-rows thead th, .prs-table-pin-rows tfoot th) {
z-index: 1;
}
:where(.prs-table-pin-rows tfoot tr) {
top: auto;
bottom: 0;
}
:where(.prs-table-pin-cols tr th) {
background: var(--prs-c-white);
position: sticky;
left: 0;
right: 0;
}
}
.prs-cell-name > :where(:first-child) {
color: var(--prs-c-aqua);
}
.prs-cell-stacked {
display: flex;
flex-direction: column;
&:where(td) > :where(:not(:first-child)) {
color: var(--prs-c-gray-600);
font-size: 0.75em;
line-height: 1.125em;
}
&:where(th) > :where(:not(:first-child)) {
font-weight: 600;
font-size: inherit;
color: var(--prs-c-gray-800);
}
}
.prs-cell-end {
text-align: end;
align-items: flex-end;
justify-content: flex-end;
}
.prs-cell-actions {
display: flex;
align-items: center;
gap: 0.25rem;
}
.prs-cell-info {
color: inherit;
display: block;
flex-shrink: 0;
position: relative;
z-index: 2;
}
.prs-cell-sort {
color: inherit;
display: block;
flex-shrink: 0;
&:after {
display: block;
position: absolute;
inset: 0;
z-index: 1;
content: '';
}
svg,
.icon,
iconify-icon {
width: 1rem;
height: 1rem;
display: block;
transition-property: var(--prs-transition-property);
transition-timing-function: var(--prs-transition-timing);
transition-duration: var(--prs-transition-duration);
}
&.desc {
svg,
.icon,
iconify-icon {
transform: rotate(180deg);
}
}
}
Figma
Coming soon...