Make table rows clickable as links with tanstack-table and CSS
Elisabeth Leonhardt
Posted on November 19, 2023
You want your entire table row to be a real clickable link? Here, I present you with a practical and accesible solution.
Link to the codesandbox: Check it out!
Step 1: Create your table
Use whatever technologies you like for this: I went with React and tanstack-table, because that’s what I currently use at work.
type Items = {
ranking: number;
url: string;
name: string;
};
const data: Items[] = [
{
ranking: 1,
url: "https://google.com",
name: "Google",
},
{
ranking: 2,
url: "https://bing.com",
name: "Bing",
},
{
ranking: 3,
url: "https://yahoo.com",
name: "Yahoo",
},
];
const columnHelper = createColumnHelper<Items>();
const columns = [
columnHelper.accessor("ranking", {
cell: (info) => info.getValue(),
}),
columnHelper.accessor("name", {
cell: (info) => info.getValue(),
}),
columnHelper.accessor("url", {
cell: (info) => info.getValue(),
}),
];
export function Table() {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<div>
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id} className="table-head">
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id} className="data-rows">
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="table-cell">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}
Step 2: Add an additional column to your table
I added it on the left side, but that’s indifferent. Here, it’s filled with yellow, so you can see it.
Step 3: Put your link inside the empty column
In the small column, put the link that every row should lead to inside an anchor tag.
...
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{/*⬇️ add an extra column here */}
<th key="extra-column" aria-label="Search Engine Links"></th>
{headerGroup.headers.map((header) => (
<th key={header.id} className="table-head">
...
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id} className="data-rows">
{/*⬇️ add a cell with an empty link for every row
below the empty column header */}
<td>
<a
href={row.original.url}
aria-label={row.original.url}
className="row-link"
></a>
</td>
{row.getVisibleCells().map((cell) => (
...
Step 4: Position the link so it spans over the whole row
Now, that the link is part of the table, let’s make it overlap over the whole row with CSS:
tr {
border: 1px solid white;
position: relative;
height: 3rem;
}
.row-link {
position: absolute;
top: 0;
left: 0;
content: "";
width: 100%;
height: 3rem;
}
.data-rows:hover {
background-color: #a8a5a5;
}
I added a yellow background and borders to every element, so it’s easier to see. With the absolute positioning in relation to the table row, the anchor tag spans over the whole row and makes it clickable.
By adding an adequate outline to the anchor tag, the focus is also including the whole row and making it therefore great to tab through. 🥳
⚠️Notes about Accessibility⚠️
- 🧑🏽🦯 The empty column header and the empty anchor tags can be confusing for people using screen readers, this is why I added an aria-attribute to them.
- ⤵️ I customized the outline for focus-visible, so the links are clearly marked as something clickable and accessible over the keyboard.
- 🎨 Mine is of course an example to show the concept - always check for sufficient contrast when choosing your colors.
I love this solution - it's so elegant! Hope this helped you!
Posted on November 19, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.