<div class="wrapper">
  <div class="card">CSS GRADIENTS</div>
  <div class="card">CSS VARIABLES</div>
  <div class="card">JAVASCRIPT</div>
</div>
@import url("https://fonts.googleapis.com/css2?family=Space+Mono:wght@700&display=swap");

body {
  overflow: hidden;
}

.wrapper {
  height: 100vh;
  width: 100%;
  background-color: #130042;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.6s;
  overflow: hidden;

  &:before {
    content: "";
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: 100%;
    height: 100%;
    background: radial-gradient(
      circle closest-side,
      rgba(255, 255, 255, 0.5),
      transparent
    );
    transform: translate(-50%, -50%) scale(var(--scale));
    transition: transform 0.2s;
  }
}

.card {
  width: 200px;
  font-family: "Space Mono", monospace;
  height: 200px;
  margin: 0 20px;
  background-color: rgba(255, 255, 255, 0.1);
  color: #fff;
  padding: 22px;
  flex-shrink: 0;
  font-size: 24px;
  text-shadow: 0 1px 0 #130042;
  box-sizing: border-box;
  border-radius: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: 0 0 100px #130042;
  transform: rotateX(var(--rotateX)) rotateY(var(--rotateY));
}
View Compiled
const card = document.querySelector(".card:nth-child(2)");
const wrapper = document.querySelector(".wrapper");

const rotateCard = (card, x, y) => {
  const coords = card.getBoundingClientRect();

  const cardX = coords.left + card.offsetWidth / 2;
  const cardY = coords.top + card.offsetHeight / 2;

  const angleX = (cardY - y) / 20;
  const angleY = (cardX - x) / -20;

  wrapper.style.setProperty("--rotateX", `${angleX}deg`);
  wrapper.style.setProperty("--rotateY", `${angleY}deg`);
};

wrapper.addEventListener("mousemove", (e) => {
  const rect = wrapper.getBoundingClientRect();
  const { top, left } = rect;
  const { x, y, clientX, clientY } = e;

  const gradientX = clientX - left;
  const gradientY = clientY - top;

  rotateCard(card, x, y);
  wrapper.style.setProperty("--x", gradientX + "px");
  wrapper.style.setProperty("--y", gradientY + "px");
});

wrapper.addEventListener("mouseenter", () => {
  wrapper.style.setProperty("--scale", "1");
});

wrapper.addEventListener("mouseleave", () => {
  wrapper.style.setProperty("--scale", "0");
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.6.1/randomColor.min.js