JSFiddle - React, Tailwind, and code Playground
by stitot
HTML
<div class="table-wrapper my-theme">
<table class="my-table">
<thead>
<tr>
<th data-column-id="col-1">Col 1</th>
<th data-column-id="col-2">Col 2</th>
<th data-column-id="col-3">Col 3</th>
<th data-column-id="col-4">Col 4</th>
<th data-column-id="col-5">Col 5</th>
<th data-column-id="col-6">Col 6</th>
<th data-column-id="col-7">Col 7</th>
</tr>
</thead>
<tbody>
<tr>
<td data-column-id="col-1" data-value="1,1">1,1</td>
<td data-column-id="col-2" data-value="1,2">1,2</td>
<td data-column-id="col-3" data-value="1,3">1,3</td>
<td data-column-id="col-4" data-value="1,4">1,4</td>
<td data-column-id="col-5" data-value="1,5">1,5</td>
<td data-column-id="col-6" data-value="1,6">1,6</td>
<td data-column-id="col-7" data-value="1,7">1,7</td>
</tr>
<tr>
<td data-column-id="col-1" data-value="2,1">2,1</td>
<td data-column-id="col-2" data-value="2,2">2,2</td>
<td data-column-id="col-3" data-value="2,3">2,3</td>
<td data-column-id="col-4" data-value="2,4">2,4</td>
<td data-column-id="col-5" data-value="2,5">2,5</td>
<td data-column-id="col-6" data-value="2,6">2,6</td>
<td data-column-id="col-7" data-value="2,7">2,7</td>
</tr>
<tr>
<td data-column-id="col-1" data-value="3,1">3,1</td>
<td data-column-id="col-2" data-value="3,2">3,2</td>
<td data-column-id="col-3" data-value="3,3">3,3</td>
<td data-column-id="col-4" data-value="3,4">3,4</td>
<td data-column-id="col-5" data-value="3,5">3,5</td>
<td data-column-id="col-6" data-value="3,6">3,6</td>
<td data-column-id="col-7" data-value="3,7">3,7</td>
</tr>
<tr>
<td data-column-id="col-1" data-value="4,1">4,1</td>
<td data-column-id="col-2" data-value="4,2">4,2</td>
<td data-column-id="col-3" data-value="4,3">4,3</td>
<td data-column-id="col-4"...
CSS
/* ----------------------------------------------------------
1) ISOLATION + BASE VARIABLES
------------------------------------------------------------*/
.table-wrapper {
all: revert;
--cell-padding: 8px;
--border-color: #ccc;
}
/*
Optional theme variables:
Row:
--row-bg
--row-even-bg
--row-hover-bg
Column:
--col-bg
--col-even-bg
--col-hover-bg
Cell:
--cell-bg
--cell-hover-bg
--cell-special-bg
Text:
--cell-color
*/
/* ----------------------------------------------------------
2) TABLE LAYOUT
------------------------------------------------------------*/
.my-table {
border-collapse: collapse;
width: 100%;
}
/* Row background (default state) */
.my-table tr {
--row-bg-current: var(--row-bg, transparent);
}
/* Even rows fallback:
- If --row-even-bg defined → use it
- Else → fall back to --row-bg
*/
.my-table tr:nth-child(even) {
--row-bg-current: var(--row-even-bg, var(--row-bg));
}
/* ----------------------------------------------------------
COLUMN BACKGROUNDS
------------------------------------------------------------*/
.my-table td {
/* base: col > transparent */
--cell-col-bg: var(--col-bg);
}
/* Even columns fallback:
- If --col-even-bg defined → use it
- Else → fall back to --col-bg
(no JS class required)
*/
.my-table td:nth-child(even) {
--cell-col-bg: var(--col-even-bg, var(--col-bg));
}
.my-table th {
padding: var(--cell-padding);
border: 1px solid var(--border-color);
text-align: left;
}
/* ----------------------------------------------------------
3) NORMAL CELL RENDERING
------------------------------------------------------------*/
.my-table td {
padding: var(--cell-padding);
border: 1px solid var(--border-color);
/* Priority: cell > column > row > transparent */
background-color: var(
--cell-bg,
var(--cell-col-bg,
...
JavaScript
document.addEventListener("DOMContentLoaded", function () {
const wrappers = document.querySelectorAll(".table-wrapper");
if (!wrappers.length) return;
wrappers.forEach((wrapper) => {
const table = wrapper.querySelector(".my-table");
if (!table) return;
// --- AUTO-ENABLE HOVER MODES ---
const cs = getComputedStyle(wrapper);
const rowHoverVal = cs.getPropertyValue("--row-hover-bg").trim();
const colHoverVal = cs.getPropertyValue("--col-hover-bg").trim();
const cellHoverVal = cs.getPropertyValue("--cell-hover-bg").trim();
if (rowHoverVal) wrapper.classList.add("row-hover-enabled");
if (colHoverVal) wrapper.classList.add("col-hover-enabled");
if (cellHoverVal) wrapper.classList.add("cell-hover-enabled");
// --- COLUMN HOVER LOGIC ---
table.addEventListener("mouseover", (event) => {
const cell = event.target.closest("td, th");
if (!cell || !table.contains(cell)) return;
clearColumnHover(table);
const colIndex = cell.cellIndex;
if (colIndex < 0) return;
for (const row of table.rows) {
const colCell = row.cells[colIndex];
if (colCell) colCell.classList.add("col-hover");
}
});
table.addEventListener("mouseout", (event) => {
const cell = event.target.closest("td, th");
if (!cell || !table.contains(cell)) return;
clearColumnHover(table);
});
});
function clearColumnHover(table) {
table.querySelectorAll(".col-hover").forEach((cell) =>
cell.classList.remove("col-hover")
);
}
});