Why does my CSS text scaling animation create a "curving" motion and how can I eliminate it?

Viewed 43

Please note: I am pretty new to CSS so I may use incorrect terminology or awkward descriptions. Also, my usage of the hover psuedo-class is simply to make it easy to demonstrate in my examples. I am NOT using any psuedo-class in my actual code.

The following snippet is a very simple CSS transition that I am applying to some text. It works exactly as I want it to except that in order to invoke the transition/animation I have to use JavaScript to manually add the effect class to the element.

.effect:hover {
  transform-origin: left top;
  transform: scale(.5, .5);
  transition: transform 1s;
}
<div>
  <span style="display: inline-block; font-size: x-large;" class="effect">HOVER OVER THIS</span>
</div>

I would much rather implement this transition/animation effect without having to write any JavaScript if possible. So I wrote the below snippet that is invoked immediately when the CSS interpreter evaluates the animation property:

.effect:hover {
  animation: 1s shrink forwards;
}
@keyframes shrink {
  to {
    transform-origin: left top;
    transform: scale(.5, .5);
  }
}
<div>
  <span style="display: inline-block; font-size: x-large;" class="effect">HOVER OVER THIS</span>
</div>

After running both of these snippets and comparing the result you should immediately see the problem I am having. The animation in the second snippet is adding something extra to the movement of the text as it shrinks... It's almost like a "curving" motion. Not sure how else to describe it.

Does anyone know what is going on here and how I can eliminate this "curving" behavior?

1 Answers

This is because the default transform-origin is 50%, 50% 0 (x-axis, y-axis, z-axis). So right now the transform-origin moves from 50%, 50% 0 to top left 0 causing the element to "curve inwards" while scaling down.

Try this:

.effect {
  transform-origin: left top;
}

.effect:hover {
  animation: 1s shrink;
}

@keyframes shrink {
  from {
    transform: scale(1, 1);
  }
  to {
    transform: scale(.5, .5);
  }
}
<div>
  <span style="display: inline-block; font-size: x-large;" class="effect">HOVER OVER THIS</span>
</div>

Related