5

I'm using a transform scaleY animation on a div, to animate its hegiht cheaply, but it doesn't work very well when there is a box-shadow applied to it.

div {
    width: 300px;
    height: 100px;
    transform: scaleY(1);
    transition: all 2000ms;
    transform-origin: 0 0;
    background-color: yellow;
    box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14),
                0 1px 10px 0 rgba(0, 0, 0, 0.12),
                0 2px 4px -1px rgba(0, 0, 0, 0.4);
}
div:hover {
    transform: scaleY(5);
}
<div></div>

jsbin.com demo

You can see the box-shadow gets scaled too. Not only that, but it snaps at the end of the animation, which looks ugly.

Any suggestions on how to keep this a quick 60fps transform animation while not scaling the shadow? Animating the height gets the desired effect but it lags A LOT on mobile.

Already tried

Applying the shadow to a div::after pseudo-element and transforming the div doesn't work as the shadow is also scaled.

doplumi
  • 2,938
  • 4
  • 29
  • 45
  • Will you final code have some content in the `div` that also needs to be scaled? Or do you only wand to change the height of the `div`? – t.niese Aug 27 '16 at 11:38
  • Let's suppose we don't care what happens to the content here. – doplumi Aug 27 '16 at 11:57
  • 1
    I overlooked that you wrote that animating the `height` would not be an option. As of that I think there is right now no real solution for your problem. That the shadow is scaled is imho intended because `scaleY` would scale everything that belongs to the object and its content. And the effect you see at the end of the animation looks like a bug of the render engine. – t.niese Aug 27 '16 at 12:19
  • Thank you, I made the `height` argument clearer in the last edit. – doplumi Aug 27 '16 at 12:48
  • The only workaround that comes into my mind that you could try is to use border images instead of box shadow and animate the height. But I don't know if the performance would be better. – t.niese Aug 27 '16 at 13:06

1 Answers1

2

You'd have to use another element here. Using transform on element affects its children and :after, :before pseudo elements. Shadow has to be in element above in order for this to work using transform. You could try using scaleY(1) and scale(-X) in pseudo selectors but that would not be reliable.

div {
    width: 300px;
    height: 100px;
    
    z-index: 1;
    position: relative;
    box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14),
                0 1px 10px 0 rgba(0, 0, 0, 0.12),
                0 2px 4px -1px rgba(0, 0, 0, 0.4);
}
div span {
    transform: scaleY(1);
    transition: all 2000ms ease;
    transform-origin: 0 0;
    background-color: yellow;
    display: block; 
    width: 300px; height: 100px;
} 
div:hover span {
    transform: scaleY(5);
}
<div><span></span></div>
Loji
  • 66
  • 1
  • 5
  • 1
    *"Using transform on element affects its children"*. It doesn't. If you look at the shadow in your snippet it doesn't move. ;( – doplumi Aug 27 '16 at 12:46
  • It does, but here shadow is in parent element that I didn't scale. It's in parent element, I only scale span that is inside. Did you wanted to have something like this? – Loji Aug 27 '16 at 13:14
  • I'm sorry I got confused in the comment above. Anyway, no I don't want the shadow to stay where it is. It should still be around the div without being deformed by the `transform`ation. – doplumi Aug 27 '16 at 13:46
  • It appears that this deformation is a bug in webkit, it works fine in Firefox. Keep in mind that if you would use scale to change size of element you would change size of its content as well. If you want to unfold content pure Javascript will be the fastest option. – Loji Aug 27 '16 at 14:37