Magic Cards

by Oski Krawczyk

HTML

<ul id="cards">
  <li></li>
  <li></li>
  <li></li>
</ul>

CSS

:root {
  --bg: #1E1F1F;
}

body {
  margin: 0;
  padding: 0;
  background: color-mix(in srgb, #000 20%, #1E1F1F);
}

ul {
  display: flex;
  padding: 0;
  margin: 0;
}

li {
  position: relative;
  padding: 0;
  margin: 5px;
  height: 150px;
  width: 200px;
  border-radius: 8px;
  background: var(--bg);
}

ul:hover li {
  background: radial-gradient(
    circle 280px at var(--pointer-top) var(--pointer-left), 
    color-mix(in srgb, var(--bg) 90%, oklch(67.3% 0.21 25.039)) 0%, 
    var(--bg) 60%
  ); 
}

li:after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  border: solid 2px rgba(255, 255, 255, 0.1);
  border-radius: 8px;
}

JavaScript

const cards = Array.from(document.querySelectorAll("li"))
const cardsContainer = document.querySelector("#cards")

cardsContainer.addEventListener("pointermove", (e) => {
  requestAnimationFrame(() => {
    for (const card of cards) {
      const rect = card.getBoundingClientRect()
      let x = e.clientX - rect.left
      let y = e.clientY - rect.top
      card.style.setProperty("--pointer-top", `${x}px`)
      card.style.setProperty("--pointer-left", `${y}px`)
    }
  })
})