I want a button which pulses multiple times (three or so), like in this Dribble video demo. The button pulses should have an interval between pulses of about 300-400ms, and also if the twisting effect can be achieved somehow that would be great.
I have this code so far, but the pulsing animation is not particularly close to the one described and linked above.
body {
background: black;
}
.button {
padding: 0.75em 1.5em;
border: 3px solid white;
border-radius: 15px;
}
.button:hover {
animation: pulse 4s infinite;
transition: 1s ease all;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7),
0 0 0 0 rgba(255, 255, 255, 0.5), 0 0 0 0 rgba(255, 255, 255, 0.3);
}
50% {
box-shadow: 0 0 0 10px rgba(255, 255, 255, 0),
0 0 0 20px rgba(255, 255, 255, 0), 0 0 0 30px rgba(255, 255, 255, 0);
}
100% {
box-shadow: 0 0 0 30px rgba(255, 255, 255, 0),
0 0 0 40px rgba(255, 255, 255, 0), 0 0 0 50px rgba(255, 255, 255, 0);
}
}
<button class="button">Button</button>
I want a button which pulses multiple times (three or so), like in this Dribble video demo. The button pulses should have an interval between pulses of about 300-400ms, and also if the twisting effect can be achieved somehow that would be great.
I have this code so far, but the pulsing animation is not particularly close to the one described and linked above.
body {
background: black;
}
.button {
padding: 0.75em 1.5em;
border: 3px solid white;
border-radius: 15px;
}
.button:hover {
animation: pulse 4s infinite;
transition: 1s ease all;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7),
0 0 0 0 rgba(255, 255, 255, 0.5), 0 0 0 0 rgba(255, 255, 255, 0.3);
}
50% {
box-shadow: 0 0 0 10px rgba(255, 255, 255, 0),
0 0 0 20px rgba(255, 255, 255, 0), 0 0 0 30px rgba(255, 255, 255, 0);
}
100% {
box-shadow: 0 0 0 30px rgba(255, 255, 255, 0),
0 0 0 40px rgba(255, 255, 255, 0), 0 0 0 50px rgba(255, 255, 255, 0);
}
}
<button class="button">Button</button>
How can I make my code more closely match the description and video example above?
Share Improve this question edited Mar 10 at 15:51 TylerH 21.1k79 gold badges79 silver badges114 bronze badges asked Mar 10 at 10:00 Vasil NikolovVasil Nikolov 631 silver badge3 bronze badges 7- 1 looking at some of the other buttons/effects by the same designer it seems unlikely he was simply using CSS – Professor Abronsius Commented Mar 10 at 10:15
- If you want 3 pulses, you need to add an element because you can only do before and after – mplungjan Commented Mar 10 at 10:16
- 2 I'm not sure why people are voting to close this question. The user made a good attempt at solving the problem themself, and then posted a question containing a minimal reproducible example when they got stuck. This is a good question. – Sean Commented Mar 10 at 12:18
- @VasilNikolov what do you mean by "the twisting effect"? What twisting effect? I don't see one on the Dribble you linked to. – TylerH Commented Mar 10 at 15:53
- Related, possible duplicate: stackoverflow/questions/44783546/… – TylerH Commented Mar 10 at 15:59
2 Answers
Reset to default 3Here is an idea using outline and pseudo-elements:
.button {
padding: 0.75em 1.5em;
border-radius: 1em;
font-size: 30px;
position: relative;
}
.button:before,
.button:after {
content:"";
position: absolute;
inset: 0;
outline: inherit;
border-radius: inherit;
}
.button:hover,
.button:hover:before,
.button:hover:after {
outline: 2px solid #fff0;
animation: pulse 2s infinite linear;
}
.button:hover:before {
animation-delay: .4s;
}
.button:hover:after {
animation-delay: .8s;
}
@keyframes pulse {
0%,10% {outline-offset:0px; outline-color:#fff0}
50% {outline-offset:20px;outline-color:#fff9}
90%,100% {outline-offset:40px;outline-color:#fff0}
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #000;
}
<button class="button">Button</button>
I updated trying to match what was in the Dribble, but it's not quite right. I can tell that you'll need to use the outlines of either extra elements and/or pseudo-elements.
Try this:
.button:hover {
animation:
pulse
400ms
cubic-bezier(1.000, 0.000, 0.000, 1.000)
both
alternate
infinite;
}
The timing function, cubic-bezier(1.000, 0.000, 0.000, 1.000)
, (aka ease-in-out-expo
), has an arrhythmic stutter. The direction, alternate
allows the transition to swing from one end of a cycle and continue from the opposite end in the beginning of the next cycle. The fill mode of both
allows the animation to extend in both directions.
*,
*::before,
*::after {
box-sizing: border-box;
}
:root {
font: 2ch/1.5 'RailroadRoman', sans-serif;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #000;
overflow-x: hidden;
}
main {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: center;
align-content: center;
gap: 2rem;
width: 100%;
min-height: 100vh;
margin: 0 auto;
background: #000;
}
button {
position: relative;
width: min-content;
width: 5rem;
height: 2rem;
padding-inline: 0.5rem;
border: 2px solid #fff;
border-radius: 8px;
outline-width: 2px;
outline-style: solid;
outline-color: #fff;
outline-offset: 0;
font: inherit;
cursor: pointer;
}
button i {
position: absolute;
top: -0.5em;
right: -0.5em;
z-index: 500;
display: block;
font-style: normal;
font-size: 1.5em;
cursor: pointer;
}
.A.yang:hover {
animation: pulse 600ms cubic-bezier(1.000, 0.000, 0.000, 1.000) both alternate infinite;
}
.A.ying:hover {
animation: pulse 2s cubic-bezier(0.445, 0.050, 0.550, 0.950) infinite;
}
@keyframes pulse {
0% {
box-shadow:
0 0 0 0 rgba(255, 255, 255, 0.7),
0 0 0 0 rgba(255, 255, 255, 0.5),
0 0 0 0 rgba(255, 255, 255, 0.3);
}
50% {
box-shadow:
0 0 0 10px rgba(255, 255, 255, 0),
0 0 0 20px rgba(255, 255, 255, 0),
0 0 0 30px rgba(255, 255, 255, 0);
}
100% {
box-shadow:
0 0 0 30px rgba(255, 255, 255, 0),
0 0 0 40px rgba(255, 255, 255, 0),
0 0 0 50px rgba(255, 255, 255, 0);
}
}
.B::before,
.B::after {
content: "";
position: absolute;
top: 0;
left: 0;
display: block;
width: 5rem;
height: 2rem;
border-radius: 8px;
outline-width: 2px;
outline-style: solid;
outline-color: #fff;
outline-offset: 0;
background: transparent;
}
.B.ying:hover::before {
z-index: 80;
animation: eb 2s ease-in backwards infinite;
}
.B.ying:hover {
z-index: 80;
animation: ripple 2s 2s ease-out both alternate infinite;
}
.B.ying:hover::after {
z-index: 120;
animation: wave 2s ease-out forwards infinite;
}
.B.yang:hover::before {
z-index: 110;
animation: wave 2s 1s ease-out backwards infinite;
}
.B.yang:hover {
z-index: 140;
animation: ripple 2s 2s ease-in-out both alternate infinite;
}
.B.yang:hover::after {
z-index: 130;
animation: eb 2s ease-out backwards infinite;
}
@keyframes ripple {
0% {
outline-width: 2px;
outline-color: transparent;
outline-offset: 0;
}
50% {
outline-width: 2px;
outline-color: #fff;
outline-offset: 30px;
}
70% {
outline-width: 2px;
outline-color: rgba(255, 55, 0 0.5);
outline-offset: 50px;
}
100% {
outline-width: 1px;
outline-color: transparent;
outline-offset: 0;
}
}
@keyframes wave {
0% {
outline-width: 1px;
outline-color: #fff;
outline-offset: 40px;
}
20% {
outline-width: 2px;
outline-color: rgba(255, 255, 10, 0.6);
outline-offset: 30px;
}
70% {
outline-width: 1px;
outline-color: rgba(255, 200, 5 0.3);
outline-offset: 10px;
}
100% {
outline-width: 1px;
outline-color: transparent;
outline-offset: 0;
}
}
@keyframes eb {
0% {
outline-width: 2px;
outline-color: transparent;
outline-offset: 0;
}
60% {
outline-width: 5px;
outline-color: rgba(55, 25, 255, 0.4);
outline-offset: 20px;
}
80% {
outline-width: 5px;
outline-color: #fff;
outline-offset: 40px;
}
100% {
outline-width: 2px;
outline-color: rgba(25, 155, 215 0.3);
outline-offset: 50px;
}
}
<link href="https://fonts.cdnfonts/css/railroadroman" rel="stylesheet">
<main>
<button class="A yang">
I <i>