JSFiddle - React, Tailwind, and code Playground
by kthornbloom
HTML
<div class="card-container">
<div class="card">
👆 Click To Complete
<button>
Finalize
</button>
</div>
</div>
CSS
@property --sweep-angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #1a2a6c; /* Dark blue background */
font-family: sans-serif;
text-align: center;
}
.card-container {
position: relative;
width: 300px;
height: 200px;
cursor: pointer; /* For demo interaction */
}
.card {
position: relative;
width: 100%;
height: 100%;
background-color: white;
border-radius: 30px;
z-index: 1;
display: flex;
flex-direction: column;
padding: 50px;
button {
padding: 1em;
border: none;
background: #4fde7d;
border-radius: 50px;
margin-top: 15px;
opacity: .2;
transition: .5s;
transition-delay: 1s;
pointer-events: none;
}
}
.card-container::after {
content: '';
position: absolute;
top: -6px;
left: -6px;
right: -6px;
bottom: -6px;
--sweep-angle: 0deg; /* Fallback for Firefox */
background: conic-gradient(from 0deg, #4fde7d var(--sweep-angle), transparent 0deg);
z-index: -1;
transition: --sweep-angle 2s linear, box-shadow 1s;
border-radius: 35px;
}
.card-container.animated::after {
animation: sweep 1s linear forwards; /* Runs once and stops */
box-shadow: 0 0 15px #4fde7d;
}
.card-container.animated {
button {
opacity: 1;
pointer-events: normal;
box-shadow: 0 0 15px #4fde7d;
}
}
@keyframes sweep {
0% { --sweep-angle: 0deg; }
100% { --sweep-angle: 360deg; }
}
* {
box-sizing:border-box;
}
JavaScript
const container = document.querySelector('.card-container');
container.addEventListener('click', () => {
container.classList.toggle('animated');
});