Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS3: Smooth transition between animations change on :hover

I have an elements that has infinite css3 animation that is changed to another infinite animation when element is hovered. Everything is ok, but sometimes animation changing is too bouncy, is there a way to make transition between animations smooth (maybe bringing element to the initial state between animations) on mouseenter and mouseleave? The starting and ending states of both animations are the same.

@keyframes first-animation {
0% { transform: scale3d(1,1,0);}
50% { transform: scale3d(0.8,0.8,0); }
100% { transform: scale3d(1,1,0); }
};

@keyframes second-animation {
0% { transform: scale3d(1,1,0); }
70% { transform: scale3d(0.7,0.7,0); }
80% { transform: scale3d(0.9,0.9,0); }
100% { transform: scale3d(1,1,0);  }
};

div{
animation: first-animation 1.7s ease-in-out infinite;
}

div:hover, div:focus{
animation: second-animation 1.1s ease-in-out infinite;
}
like image 389
vlad Avatar asked Mar 07 '14 17:03

vlad


People also ask

How do I make transitions smoother in CSS?

With CSS3 we can specify how an element changes by just describing its current and target states. CSS3 will create a smooth transition between these states by applying a cubic Bézier curve and gradually change the element appearance.

Does transition only work with hover?

But transitions are not just limited to use with :hover . You can animate CSS properties, thus use CSS transitions without hover. This is done via transitions using some other CSS techniques, a number of which I've outlined below. I've also included a demo for each example.

How do you stop hover transition in CSS?

By setting the animation-play-state to paused on hover, the animation will pause, your click targets will stop moving, and your users will be happy.


2 Answers

I don't think that it can be achieved using the scale transforms.

You can do a trick and change from scale() to translateZ(). When a perspective is applied, the net effect will be also a scale. But the interesting point is than setting perspective to a high value, this scale effect can be made very small. And perspective is an animatable property.

The downside is that we will need to add 2 wrap around layers... but the final result is this. I have kept the original version to compare

@keyframes first-animation {
0% { transform: scale(1,1);}
50% { transform: scale(0.8,0.8); }
100% { transform: scale(1,1); }
}

@keyframes second-animation {
0% { transform: scale(1,1); }
70% { transform: scale(0.7,0.7); }
80% { transform: scale(0.9,0.9); }
100% { transform: scale(1,1);  }
}

.sample {
    background-color: lightblue;
    animation: first-animation 1.7s ease-in-out infinite;
}

.sample:hover {
animation: second-animation 1.1s ease-in-out infinite;
}

.dim {
    width: 200px;
    height: 200px;
}

.base1 {
    perspective: 1000px;
    transition: perspective 2s ease-out;
    position: absolute;
    left: 300px;
  top: 10px;
}
.base1:hover {
    perspective: 9999px;
}

.base2 {
    width: 100%;
    height: 100%;
    animation: animation1 1.7s ease-in-out infinite;
    perspective: 9999px;
    transition: perspective 2s ease-in;
}
.base1:hover .base2 {
    perspective: 1000px;
}

.inner {
    width: 100%;
    height: 100%;
    background-color: lightgreen;
    animation: animation2 1.1s ease-in-out infinite;
    transform-style: preserve-3d;
    perspective: 99999px;
}

@keyframes animation1 {
0% { transform: translateZ(0px);}
50% { transform: translateZ(-200px); }
100% { transform: translateZ(0px); }
}

@keyframes animation2 {
      0% { transform: translateZ(0px);}
     70% { transform: translateZ(-300px); }
     80% { transform: translateZ(-100px); }
    100% { transform: translateZ(0px); }
}
<div class="sample dim">SAMPLE</div>
<div class="base1 dim">
    <div class="base2">
        <div class="inner">DEMO</div>
    </div>
</div>
like image 189
vals Avatar answered Sep 21 '22 09:09

vals


In order to get the desired effect then you will need to use the css3 animation events. in this case you need to use "AnimationIteration". So you can fire an event after an iteration. I have added a class to the end of this event for the second animation.

Codepen Demo

$(document).ready(function() {
  var animationElement = $(".animation");

  $("body").on({
    mouseover: function() {
      animationElement.one('webkitAnimationIteration mozAnimationIteration AnimationIteration', function() {
        animationElement.addClass("second-animation");
      });
    },
    mouseleave: function() {
      animationElement.one('webkitAnimationIteration mozAnimationIteration AnimationIteration', function() {
        animationElement.removeClass("second-animation");
      });
    }
  });
});
like image 31
2ne Avatar answered Sep 19 '22 09:09

2ne