I’m having an issue with mix-blend-mode in my HTML/CSS table. I want to highlight rows and columns in a table when hovering over cells, but the mix-blend-mode effect only works as expected for rows, not columns.
I applied mix-blend-mode to cells with a .filled class for both rows and columns. I expected the blending effect to work for both highlighted rows and columns. The blending effect works for rows but not for columns. The column highlighting does not show the expected color blending.
const table = document.getElementById('scores-table');
const rows = table.getElementsByTagName('tr');
table.addEventListener('mouseover', function(e) {
const target = e.target;
if (target.tagName === 'TD') {
const cellIndex = target.cellIndex;
const rowIndex = target.parentElement.rowIndex;
// Remove previous highlights
Array.from(rows).forEach(row => {
Array.from(row.children).forEach(cell => {
cell.classList.remove('highlighted-column');
});
row.classList.remove('highlighted-row');
});
// Highlight column
Array.from(rows).forEach(row => {
if (row.children[cellIndex]) {
row.children[cellIndex].classList.add('highlighted-column');
}
});
// Highlight row
if (rows[rowIndex]) {
rows[rowIndex].classList.add('highlighted-row');
}
}
});
table.addEventListener('mouseout', function(e) {
const target = e.target;
if (target.tagName === 'TD') {
// Remove column and row highlight
Array.from(rows).forEach(row => {
Array.from(row.children).forEach(cell => {
cell.classList.remove('highlighted-column');
});
row.classList.remove('highlighted-row');
});
}
});
table {
border-collapse: collapse;
width: 100%;
margin: 0 auto;
}
th,
td {
width: 30px;
height: 20px;
text-align: center;
border: 1px solid #ccc;
/* Border for visibility */
position: relative;
z-index: 0;
}
.highlighted-column {
background-color: rgba(211, 211, 211, 0.3);
/* Light grey for column highlighting */
mix-blend-mode: color;
}
.highlighted-row {
background-color: rgba(211, 211, 211, 0.3);
/* Light yellow for row highlighting */
}
td.filled {
background-color: green;
mix-blend-mode: color;
position: relative;
}
<table id="scores-table">
<tbody>
<tr>
<td class="">1</td>
<td class="filled">2</td>
<td class="filled">3</td>
</tr>
<tr>
<td class="">4</td>
<td class="">5</td>
<td class="">6</td>
</tr>
<tr>
<td class="filled">7</td>
<td class="filled">8</td>
<td class="">9</td>
</tr>
</tbody>
</table>
2
Answers
The mix-blend-mode:color works fine. It is important to know that for the same CSS property set on the same element, one will overwrite one by another (based on Specificity.)
The problem here is that on
td
the new background-color added byhighlighted-coloumns
is overwritten by the original background color fromtd.filled
. Hence, there is no two different background colors for themix-blend-mode
to work.It works on the rows because the highlighted-row’s background color is applied to the row instead of the cells.
You can either simply use a same-size
td::before
psuedo element and instead apply the gray color to it, or usingbackground-blend-mode:luminosity
(opposite ofcolor
blend mode) as shown below to get the exact same result.That being said, if the JS mouse events are only for this coloring purpose, there are definetly pure CSS solutions that may or may not be simpler depending on your actual use case. (E.g. Using a long pseudo element, or using a bunch of
:has
when the table has a fixed and small amount of rows and columns.)Here are some solutions:
Make sure that the z-index for .highlighted-column is higher than that for .highlighted-row but lower than that of the .filled cells.
Add z-index properties to control the stacking context for the highlighted elements.
adjust the blending mode for the .highlighted-row and .highlighted-column classes.