How to keep origin in center of image in scale animation?
Asked Answered
D

2

9

I have a situation similar to this fiddle, where I have a CSS3 animation that scales an element absolute-positioned in the centre of another element. However, when the animation takes place it is off-centre, as seen by the red squares relative to blue in the example. How do I centre it? I have tried a couple of configurations around the transform-origin property, but this isn't producing the correct results.

@keyframes ripple_large {
	0% {transform:scale(1); }
	75% {transform:scale(3); opacity:0.4;}
	100% {transform:scale(4); opacity:0;}
}

.container {
  position: relative;
	display: inline-block;
  margin: 10vmax;
}

.cat {
  height: 20vmax;
}

.center-point {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 10px;
  width: 10px;
  background: blue;
}

.to-animate {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid red;
  height: 5vmax;
  width: 5vmax;
  transform-origin:center;
}

.one {
		animation: ripple_large 2s linear 0s infinite;
}

.two {
		animation: ripple_large 2s linear 1s infinite;
}
<div class='container'>
  <img src='http://www.catster.com/wp-content/uploads/2017/08/Pixiebob-cat.jpg' class='cat'>
  <div class='center-point'>
  </div>
  <div class='to-animate one'></div>
  <div class='to-animate two'></div>
</div>
Demavend answered 14/12, 2017 at 19:32 Comment(0)
W
14

The issue is that you are overriding the translate transformation.

When you specify a new transformation (the one inside the animation) it override the first one. In your case you are removing the translation that is fixing the center alignment.

You need to add them to the same transform property and pay attention to the order because it's important (Why does order of transforms matter? rotate/scale doesn't give the same result as scale/rotate)

@keyframes ripple_large {
  0% {
    transform: translate(-50%, -50%) scale(1);
  }
  75% {
    transform: translate(-50%, -50%) scale(3);
    opacity: 0.4;
  }
  100% {
    transform: translate(-50%, -50%) scale(4);
    opacity: 0;
  }
}

.container {
  position: relative;
  display: inline-block;
  margin: 10vmax;
}

.cat {
  height: 20vmax;
}

.center-point {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 10px;
  width: 10px;
  background: blue;
  transform-origin: center;
}

.to-animate {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid red;
  height: 5vmax;
  width: 5vmax;
}

.one {
  -webkit-animation: ripple_large 2s linear 0s infinite;
  animation: ripple_large 2s linear 0s infinite;
}

.two {
  -webkit-animation: ripple_large 2s linear 1s infinite;
  animation: ripple_large 2s linear 1s infinite;
}
<div class='container'>
  <img src='http://www.catster.com/wp-content/uploads/2017/08/Pixiebob-cat.jpg' class='cat'>
  <div class='center-point'>
  </div>
  <div class='to-animate one'></div>
  <div class='to-animate two'></div>
</div>

UPDATE

As commented, it's better to center your element using another method than translation to avoid changing the animation since this can be used with other elements.

Example:

@keyframes ripple_large {
  0% {
    transform: scale(1) ;
  }
  75% {
    transform:scale(3) ;
    opacity: 0.4;
  }
  100% {
    transform: scale(4) ;
    opacity: 0;
  }
}

.container {
  position: relative;
  display: inline-block;
  margin: 10vmax;
}

.cat {
  height: 20vmax;
}

.center-point {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 10px;
  width: 10px;
  background: blue;
  transform-origin:center;
}

.to-animate {
  position: absolute;
  top: 0;
  left: 0;
  bottom:0;
  right:0;
  margin:auto;
  border: 1px solid red;
  height: 5vmax;
  width: 5vmax;
}

.one {
  animation: ripple_large 2s linear 0s infinite;
}

.two {
  animation: ripple_large 2s linear 1s infinite;
}
<div class='container'>
  <img src='http://www.catster.com/wp-content/uploads/2017/08/Pixiebob-cat.jpg' class='cat'>
  <div class='center-point'>
  </div>
  <div class='to-animate one'></div>
  <div class='to-animate two'></div>
</div>
Weald answered 14/12, 2017 at 19:39 Comment(4)
Either that or use (in this specific case) margin to center the element, since the width/height are fixed. In case they want to keep the keyframes agnostic to the element that it is applied.Ogdon
@GabyakaG.Petrioli yes sure ;) i focused on the way they override and added them to animation to show it. But i agree that it's better to fix alignement in other way :)Weald
Not sure if my suggestion is really better, i just wanted to mention an alternative solution.Ogdon
@GabyakaG.Petrioli i think in general it's better as we can for example consider the case where we use some external library that add animation on transform and in this case we cannot change the animation and it's better to change CSS of our element.Weald
D
1

By using transform: scale(1); onto an already defined transform property like transform: translate(-50%, -50%); you will lose (override) the translate with scale-only.

Either

  • repeat the desired like transform: translate(-50%, -50%) scale(1); or rather:
  • use the CSS3 scale: and translate: properties on their own:

@keyframes ripple_large {
  0% {
    scale: 1;  /* CHANGED THIS */
  }
  75% {
    scale: 3;  /* CHANGED THIS */
    opacity: 0.4;
  }
  100% {
    scale: 4;  /* CHANGED THIS */
    opacity: 0;
  }
}

.container {
  position: relative;
  display: inline-block;
  margin: 10vmax;
}

.cat {
  height: 20vmax;
}

.center-point {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%; /* CHANGED THIS */
  height: 10px;
  width: 10px;
  background: blue;
}

.to-animate {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%; /* CHANGED THIS */
  border: 1px solid red;
  height: 5vmax;
  width: 5vmax;
  transform-origin: center;
}

.one {
  animation: ripple_large 2s linear 0s infinite;
}

.two {
  animation: ripple_large 2s linear 1s infinite;
}
<div class="container">
  <img src="https://i.sstatic.net/LBCIk.jpg" class="cat">
  <div class="center-point">
  </div>
  <div class="to-animate one"></div>
  <div class="to-animate two"></div>
</div>
Disaccord answered 22/8, 2023 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.