<div class="container">
<button class="button">Tricky Button</button>
</div>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
position: relative;
background: #eee;
}
.container {
overflow: hidden;
width: 100%;
max-width: 600px;
margin: 0 auto;
position: relative;
background: #fff;
height: 200px;
border-radius: 12px;
display: flex;
justify-content: center;
align-items: center;
}
.button {
display: inline-flex;
background-color: #3f51b5;
position: relative;
transition: transform 0.3s ease;
padding: 10px 20px;
text-align: center;
border-radius: 5px;
color: #fff;
font-size: 16px;
font-family: "Roboto", sans-serif;
white-space: nowrap;
}
.active {
transform: translateX(150px);
}
.destroy {
transform: translateX(0px);
}
const animateElement = async (config) => {
const { target, action, animateClass } = config;
const launchAnimate = () => {
return new Promise((resolve) => {
target.classList.add(animateClass, "is-moved");
const handleAnimateEnd = (event) => {
event.stopPropagation();
target.classList.remove("is-moved");
resolve("Animation end");
};
target.addEventListener(
"transitionend",
(event) => {
return handleAnimateEnd(event);
},
{ once: true }
);
});
};
await launchAnimate();
action && action(target);
};
const container = document.querySelector(".container");
const button = container.querySelector(".button");
container.addEventListener("mousemove", ({ target: t }) => {
if (!t.classList.contains("button")) return;
if (button.classList.contains("is-moved")) return;
switch (button.classList.contains("active")) {
case false:
return animateElement({
target: button,
animateClass: "active"
});
case true:
return animateElement({
target: button,
animateClass: "destroy",
action: (target) => {
target.classList.remove("active");
target.classList.remove("destroy");
}
});
}
});
container.addEventListener("mouseleave", () => {
button.classList.remove("active");
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.