I've tired of several solutions and this is the closest I've gotten. But I'm still not happy with how it turned out, because when the mouse leaves the element, the element reverts to its original rotation. The idea is that if you go over the element, it will trigger the animation even if the mouse leaves the element. If you hover over the element, it will animate and stay at 0 degrees, and once the mouse leaves, another animation will play and rotate back to -8 degrees.
const elements = document.getElementsByClassName('rotate_left');
for (let i = 0; i <= elements.length; i++) {
elements[i].addEventListener('animationend', function(e) {
elements[i].classList.remove('animated')
/*elements[i].classList.add('animatedback')*/
});
elements[i].addEventListener('mouseover', function(e) {
elements[i].classList.add('animated')
elements[i].classList.remove('animatedback')
});
}
.rotate_left {
-ms-transform: rotate(-8deg);
-webkit-transform: rotate(-8deg);
transform: rotate(-8deg);
transition-duration: 1s;
transition-delay: 0.25s;
}
.polaroid {
width: 280px;
height: 200px;
padding: 10px 15px 100px 15px;
border: 1px solid #BFBFBF;
border-radius: 2%;
background-color: white;
box-shadow: 10px 10px 5px #aaaaaa;
}
.polaroid:hover {
width: 280px;
height: 200px;
padding: 10px 15px -100px 15px;
border: 1px solid #BFBFBF;
border-radius: 2%;
background-color: white;
box-shadow: 10px 10px 5px #aaaaaa;
-ms-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
transition-duration: 1s;
transition-delay: 0.25s;
}
@keyframes animationBegining {
from {
-ms-transform: rotate(-8deg);
/* IE 9 */
-webkit-transform: rotate(-8deg);
/* Safari */
transform: rotate(-8deg);
}
to {
-ms-transform: rotate(0deg);
/* IE 9 */
-webkit-transform: rotate(0deg);
/* Safari */
transform: rotate(0deg);
}
}
@keyframes animatedBack {
form {
-ms-transform: rotate(0deg);
/* IE 9 */
-webkit-transform: rotate(0deg);
/* Safari */
transform: rotate(0deg);
}
to {
-ms-transform: rotate(-8deg);
/* IE 9 */
-webkit-transform: rotate(-8deg);
/* Safari */
transform: rotate(-8deg);
}
}
.animatedback {
animation: animatedBack 2s;
}
.animated {
animation: animationBegining 2s;
}
<div id="modalWrepper1" class="polaroid rotate_left"> <p class="caption">Just a basic explanation of the picture.</p> </div>
Thank you for your help.
Once the mouse leaves the element, there is a smooth animation back to the original rotation.
Pure CSS solution (second animation needs to be prevented)
You don’t need JS or any fancy classes.
transformandtransition-durationwill do.Let's start with the HTML; this is still your code, but simplified:
Now, the main part: CSS. Since your card is rotated by -8 degrees by default, we've added a rule to do this:
.rotate_left { transform: rotate(-8deg); transition-duration: 1s; transition-delay: 0.25s; }If you hover
. Polaroidover it, it will rotate back to 0 degrees. This means we can use the pseudo class:hover:.polaroid:hover { transform: rotate(0deg); }Once you move the mouse away from
.poloid, the:hoverrules no longer apply. This means it will revert to the previous rule within 1 second, starting 0.25 seconds after the mouse is gone.try it:
.rotate_left { transform: rotate(-8deg); transition-duration: 1s; transition-delay: 0.25s; } .polaroid:hover { transform: rotate(0deg); } /* Demo only */ .polaroid { border: 1px solid #bfbfbf; border-radius: 2%; padding: 10px 15px; height: 200px; width: 280px; box-shadow: 10px 10px 5px #aaa; }Prevent the second animation from stopping
To prevent recovery from stalling, some JS is required.
First, we declare some constants:
const card = document.querySelector('.rotate_left'); const duration = 1000; // Duration of animation, in milliseconds. const delay = 250; // Delay before animation, in milliseconds. const keyframes = [ { transform: 'rotate(-8deg)' }, { transform: 'rotate(0deg)' }, ]; const options = { duration, delay, fill: 'forwards' };Then we create a handler:
const handler = () => { // New mouse over & leave should not mess with current animation. if (card.classList.contains('rotating')) { return; } // Let ourselves know that an animation is playing. card.classList.add('rotating'); let animation; if (card.classList.contains('not_rotated')) { // Rotated to 0 degree, reverting. animation = card.animate([...keyframes].reverse(), options); } else { animation = card.animate(keyframes, options); } // Make sure we clean after ourselves after animation. animation.finished.then(() => { card.classList.remove('rotating'); card.classList.toggle('not_rotated'); }); };Add this as an event handler for
'mouseover'/'mouseleave'and we're done:card.addEventListener('mouseover', handler); card.addEventListener('mouseleave', handler);try it:
const card = document.querySelector('.rotate_left'); const duration = 1000; // Duration of animation, in milliseconds. const delay = 250; // Delay before animation, in milliseconds. const keyframes = [ { transform: 'rotate(-8deg)' }, { transform: 'rotate(0deg)' }, ]; const options = { duration, delay, fill: 'forwards' }; const handler = () => { if (card.classList.contains('rotating')) { return; } card.classList.add('rotating'); let animation; if (card.classList.contains('not_rotated')) { animation = card.animate([...keyframes].reverse(), options); } else { animation = card.animate(keyframes, options); } animation.finished.then(() => { card.classList.remove('rotating'); card.classList.toggle('not_rotated'); }); }; card.addEventListener('mouseover', handler); card.addEventListener('mouseleave', handler);.rotate_left { transform: rotate(-8deg); } /* Demo only */ .polaroid { border: 1px solid #bfbfbf; border-radius: 2%; padding: 10px 15px; height: 200px; width: 280px; box-shadow: 10px 10px 5px #aaa; }