<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
This Pen doesn't use any external CSS resources.