Заметка создана: 30 марта 2025 г.
Создаём эффект свечения ячеек таблицы при наведении курсора, как в календаре windows 10.
Решение основывается на том, что под список с ячейками календаря добавляется такой же список с пустыми ячейками subcell, для которых задан постоянный цвет границы, отличающийся от фона. Оба списка помещаются в grid-контейнер и накладываются друг на друга, а между ними помещается пустой div shadow с радиальным градиентом, цвет в градиенте не меняется, меняется только прозрачность - она становится максимальной в центре. Далее этот shadow "привязывается" своим центром к курсору. Может кому то пригодится.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<ul class="list list-subcells"></ul>
<div class="shadow"></div>
<ul class="list list-cells"></ul>
</div>
<template id="cell-template">
<li class="cell">
<span class="cell-number"></span>
</li>
</template>
<template id="subcell-template">
<li class="cell subcell"></li>
</template>
<script src="script.js"></script>
</body>
</html>
JavaScript / jQuery
const cellTemplate = document.querySelector('#cell-template').content.querySelector('.cell');
const subcellTemplate = document.querySelector('#subcell-template').content.querySelector('.subcell');
const container = document.querySelector('.container');
const sublist = document.querySelector('.list-subcells');
const list = document.querySelector('.list-cells');
const shadow = document.querySelector('.shadow');
function calcMouseCrd ({ x, y }) {
return {
x: x - container.offsetLeft - 0.5 * shadow.offsetWidth,
y: y - container.offsetTop - 0.5 * shadow.offsetHeight
};
}
function setShadowCrd ({ x, y }) {
shadow.style.left = `${x}px`;
shadow.style.top = `${y}px`;
}
(function () {
for (let i = 0; i < 30; i++) {
const cell = cellTemplate.cloneNode(true);
const subcell = subcellTemplate.cloneNode(true);
cell.querySelector('.cell-number').textContent = `${i + 1}`;
list.append(cell);
sublist.append(subcell);
}
setShadowCrd(calcMouseCrd({x: 0, y: 0}));
document.addEventListener('mousemove', (evt) => {
const { x, y } = calcMouseCrd({ x: evt.clientX, y: evt.clientY });
setShadowCrd({ x, y });
});
})();
Стили CSS
.body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #222;
}
.container {
position: relative;
display: grid;
overflow: hidden;
}
.list {
grid-row: 1/2;
grid-column: 1/2;
display: grid;
grid-template-columns: repeat(7, auto);
gap: 3px;
z-index: 1;
}
.list-subcells {
z-index: 0;
}
.shadow {
position: absolute;
width: 200vw;
aspect-ratio: 1.0;
background: radial-gradient(rgba(34, 34, 34, 0), #222 100px);
}
.cell {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
aspect-ratio: 1.0;
border: 2px solid transparent;
color: #eaeaea;
list-style: none;
user-select: none;
}
.cell:hover {
border-color: #999;
}
.subcell {
border-color: #666;
pointer-events: none;
}