1

Trying to create an animated mic component using the Web Speech API which I'll toggle based whether it's listening or not. While it's on listening mode, I want to show a animated ripple effect which is implemented on scaling it via keyframes. I'm also positioning the ripple pseudo element absolutely in center for which I'm using translate too which disrupts its transform-origin. I tried setting it in center but it isn't working. Any idea why?

.mic-container{
  width: 52px;
  height: 166px;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid #6593c3;
  border-radius: 3px;
}
button{
  background: none;
  border: none;
  outline: none;
  position: relative;
}
button::before {
  content: '';
  width: 20px;
  height: 20px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: scale(0) translate(-50%, -50%);
  transform-origin: center center;
  border-radius: 100%;
  background-color: #6593c3;
  z-index: 0;
  transition: 1.5s all ease;
  animation: ripple 1.5s infinite;
}
@keyframes ripple {
  0% {
    trasform: scale(1.2);
  }
  50% {
    transform: scale(1.8);
    opacity: 0.5;
  }
  100% {
    transform: scale(2.4);
    opacity: 0;
  }
}
<div class='mic-container'>
  <button>
    <svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 20.7129C17.5605 20.7129 19.6289 18.5156 19.6289 15.8203V6.76758C19.6289 4.07227 17.5605 1.875 15 1.875C12.4395 1.875 10.3711 4.07227 10.3711 6.76758V15.8203C10.3711 18.5156 12.4395 20.7129 15 20.7129Z" fill="#4976A6"/>
<path d="M21.5039 11.25V15.9199C21.5039 19.4473 18.5859 22.3184 15.0586 22.3184C11.5312 22.3184 8.61328 19.4473 8.61328 15.9199V11.25H7.5V15.9199C7.5 19.8574 10.6055 23.1035 14.5312 23.3906V27.0703H10.2539V28.125H19.6875V27.0703H15.6445V23.3906C19.5117 23.1035 22.5 19.8574 22.5 15.9199V11.25H21.5039Z" fill="#6593C3"/>
</svg>
  </button>
</div>
nimsrules
  • 2,026
  • 20
  • 22

2 Answers2

2

First, you should use transform-origin: 0 0;

By default, the origin of a transform is center.

transform-origin CSS property

You also have a typo here. it is transform not trasform

 0% {
    transform: scale(1.2);
  }

.mic-container {
  width: 52px;
  height: 166px;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid #6593c3;
  border-radius: 3px;
}

button {
  background: none;
  border: none;
  outline: none;
  position: relative;
}

button::before {
  content: "";
  width: 20px;
  height: 20px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: scale(0) translate(-50%, -50%);
  transform-origin: 0 0;
  border-radius: 100%;
  background-color: #6593c3;
  z-index: 0;
  transition: 1.5s all ease;
  animation: ripple 1.5s infinite;
}

@keyframes ripple {
  0% {
    transform: scale(1.2) translate(-50%, -50%);
  }
  50% {
    transform: scale(1.8) translate(-50%, -50%);
    opacity: 0.5;
  }
  100% {
    transform: scale(2.4) translate(-50%, -50%);
    opacity: 0;
  }
}
<div class='mic-container'>
  <button>
    <svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 20.7129C17.5605 20.7129 19.6289 18.5156 19.6289 15.8203V6.76758C19.6289 4.07227 17.5605 1.875 15 1.875C12.4395 1.875 10.3711 4.07227 10.3711 6.76758V15.8203C10.3711 18.5156 12.4395 20.7129 15 20.7129Z" fill="#4976A6"/>
<path d="M21.5039 11.25V15.9199C21.5039 19.4473 18.5859 22.3184 15.0586 22.3184C11.5312 22.3184 8.61328 19.4473 8.61328 15.9199V11.25H7.5V15.9199C7.5 19.8574 10.6055 23.1035 14.5312 23.3906V27.0703H10.2539V28.125H19.6875V27.0703H15.6445V23.3906C19.5117 23.1035 22.5 19.8574 22.5 15.9199V11.25H21.5039Z" fill="#6593C3"/>
</svg>
  </button>
</div>
xperator
  • 2,743
  • 7
  • 34
  • 58
Ahmad Dalao
  • 1,968
  • 1
  • 8
  • 14
  • I get the point that I need to include ```translate``` in the keyframes too. But why does it jitter at 50% scale? – nimsrules Sep 12 '20 at 16:59
  • 1
    Because the translate didn't exist in the animation and you were overriding the transform using the scale only. That's my understanding – Ahmad Dalao Sep 13 '20 at 05:14
1

When you declare your @keyframes animation, you are writing lines of transform as such transform: scale(1.2);, thus removing the translate part that you set previously.

You will also need to set the original element like this:

  transform-origin: 0 0;
  transform: scale(3) translate(-50%, -50%);

To have it work properly, you would have to keep the translate part in your transform declaration, like this :

@keyframes ripple {
  0% {
    trasform: scale(1.2) translate(-50%, -50%);
  }
  50% {
    transform: scale(1.8) translate(-50%, -50%);
    opacity: 0.5;
  }
  100% {
    transform: scale(2.4) translate(-50%, -50%);
    opacity: 0;
  }
ArnaudV
  • 342
  • 2
  • 9