Why does keyframe animation repeat more than once? - html

.a.b{
border: 2px solid red;
animation-name: appear;
animation-duration: 1s;
animation-iteration-count: 1;
}
#keyframes appear{
from{opacity:0;
transform:rotateZ(20deg);
top:100;}
to{opacity:1;
top:0;
transform:rotate(0);}
}
#keyframes zoomer{
from{
opacity:0.5;
}
to{
opacity:1;
}
}
.a.b:hover{
animation: zoomer 1s linear 1;
}
<html>
<head>
</head>
<body>
<div>
<h1 class="a b">hello world</h1>
</div>
</body>
</html>
In the above code snippet, why does the #keyframes animation repeat when I use hover? The number of iterations are specified as 1.
My guess is that the class associated with the <h1> tag changes when we hover and then again changes when we remove the mouse. But how are we going to fix it?

The animation is triggering because the :hover pseudoclass overrides<h1>'s animation property. When the pseudoclass is removed, the animation property "changes" again, back to its original value, which triggers the animation.
There are a few ways you could get around this behavior. If you want to have the <h1> animate on load, but never again, consider creating a separate class:
.a.b.onload {
animation-name: appear;
animation-duration: 1s;
animation-iteration-count: 1;
}
Then in Javascript, remove the class after waiting 1 second for the initial animation to finish:
window.addEventListener("DOMContentLoaded", () => {
setTimeout( () => {
document.querySelector(".a.b").classList.remove("onload")
}, 1000);
});

Related

How do I pause an animation? [duplicate]

So, it is possible to have reverse animation on mouse out such as:
.class{
transform: rotate(0deg);
}
.class:hover{
transform: rotate(360deg);
}
but, when using #keyframes animation, I couldn't get it to work, e.g:
.class{
animation-name: out;
animation-duration:2s;
}
.class:hover{
animation-name: in;
animation-duration:5s;
animation-iteration-count:infinite;
}
#keyframe in{
to {transform: rotate(360deg);}
}
#keyframe out{
to {transform: rotate(0deg);}
}
What is the optimal solution, knowing that I'd need iterations and animation itself?
http://jsfiddle.net/khalednabil/eWzBm/
I think that if you have a to, you must use a from.
I would think of something like :
#keyframe in {
from: transform: rotate(0deg);
to: transform: rotate(360deg);
}
#keyframe out {
from: transform: rotate(360deg);
to: transform: rotate(0deg);
}
Of course must have checked it already, but I found strange that you only use the transform property since CSS3 is not fully implemented everywhere. Maybe it would work better with the following considerations :
Chrome uses #-webkit-keyframes, no particuliar version needed
Safari uses #-webkit-keyframes since version 5+
Firefox uses #keyframes since version 16 (v5-15 used #-moz-keyframes)
Opera uses #-webkit-keyframes version 15-22 (only v12 used #-o-keyframes)
Internet Explorer uses #keyframes since version 10+
EDIT :
I came up with that fiddle :
http://jsfiddle.net/JjHNG/35/
Using minimal code. Is it approaching what you were expecting ?
Its much easier than all this: Simply transition the same property on your element
.earth { width: 0.92%; transition: width 1s; }
.earth:hover { width: 50%; transition: width 1s; }
https://codepen.io/lafland/pen/MoEaoG
I don't think this is achievable using only CSS animations. I am assuming that CSS transitions do not fulfil your use case, because (for example) you want to chain two animations together, use multiple stops, iterations, or in some other way exploit the additional power animations grant you.
I've not found any way to trigger a CSS animation specifically on mouse-out without using JavaScript to attach "over" and "out" classes. Although you can use the base CSS declaration trigger an animation when the :hover ends, that same animation will then run on page load. Using "over" and "out" classes you can split the definition into the base (load) declaration and the two animation-trigger declarations.
The CSS for this solution would be:
.class {
/* base element declaration */
}
.class.out {
animation-name: out;
animation-duration:2s;
}
.class.over {
animation-name: in;
animation-duration:5s;
animation-iteration-count:infinite;
}
#keyframes in {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#keyframes out {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
And using JavaScript (jQuery syntax) to bind the classes to the events:
$(".class").hover(
function () {
$(this).removeClass('out').addClass('over');
},
function () {
$(this).removeClass('over').addClass('out');
}
);
Creating a reversed animation is kind of overkill to a simple problem. What you need is:
animation-direction: reverse
However, this won't work on its own because animation spec forgot to add a way to restart the animation, so here is how you do it with the help of JS
let item = document.querySelector('.item')
// play normal
item.addEventListener('mouseover', () => {
item.classList.add('active')
})
// play in reverse
item.addEventListener('mouseout', () => {
item.style.opacity = 0 // avoid showing the init style while switching the 'active' class
item.classList.add('in-active')
item.classList.remove('active')
// force dom update
setTimeout(() => {
item.classList.add('active')
item.style.opacity = ''
}, 5)
item.addEventListener('animationend', onanimationend)
})
function onanimationend() {
item.classList.remove('active', 'in-active')
item.removeEventListener('animationend', onanimationend)
}
#keyframes spin {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(180deg);
}
}
div {
background: black;
padding: 1rem;
display: inline-block;
}
.item {
/* because span cant be animated */
display: block;
color: yellow;
font-size: 2rem;
}
.item.active {
animation: spin 1s forwards;
animation-timing-function: ease-in-out;
}
.item.in-active {
animation-direction: reverse;
}
<div>
<span class="item">ABC</span>
</div>
we can use requestAnimationFrame to reset animation and reverse it when browser paints in next frame.
Also use onmouseenter and onmouseout event handlers to reverse animation direction
As per
Any rAFs queued in your event handlers will be executed in the ​same
frame​. Any rAFs queued in a rAF will be executed in the next frame​.
function fn(el, isEnter) {
el.className = "";
requestAnimationFrame(() => {
requestAnimationFrame(() => {
el.className = isEnter? "in": "out";
});
});
}
.in{
animation: k 1s forwards;
}
.out{
animation: k 1s forwards;
animation-direction: reverse;
}
#keyframes k
{
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
<div style="width:100px; height:100px; background-color:red"
onmouseenter="fn(this, true)"
onmouseleave="fn(this, false)"
></div>
Would you be better off having just the one animation, but having it reverse?
animation-direction: reverse
Using transform in combination with transition works flawlessly for me:
.ani-grow {
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.ani-grow:hover {
transform: scale(1.01);
}
I've put together a CodePen with a CSS-only fix and one with 2 lines of jQuery to fix the on-page load issue. Continue reading to understand the 2 solutions in a simpler version.
https://codepen.io/MateoStabio/pen/jOVvwrM
If you are searching how to do this with CSS only, Xaltar's answer is simple, straightforward, and is the correct solution. The only downside is that the animation for the mouse out will play when the page loads. This happens because to make this work, you style your element with the OUT animation and the :hover with the IN animation.
svg path{
animation: animateLogoOut 1s;
}
svg:hover path{
animation: animateLogoIn 1s;
}
#keyframes animateLogoIn {
from {stroke-dashoffset: -510px;}
to {stroke-dashoffset: 0px;}
}
#keyframes animateLogoOut {
from {stroke-dashoffset: 0px;}
to {stroke-dashoffset: -510px;}
}
Some people found this solution to be useless as it played on page load. For me, this was the perfect solution. But I made a Codepen with both solutions as I will probably need them in the near future.
If you do not want the CSS animation on page load, you will need to use a tiny little script of JS that styles the element with the OUT animation only after the element has been hovered for the first time. We will do this by adding a class of .wasHovered to the element and style the added class with the OUT Animation.
jQuery:
$("svg").mouseout(function() {
$(this).addClass("wasHovered");
});
CSS:
svg path{
}
svg.wasHovered path{
animation: animateLogoOut 1s;
}
svg:hover path{
animation: animateLogoIn 1s;
}
#keyframes animateLogoIn {
from {stroke-dashoffset: -510px;}
to {stroke-dashoffset: 0px;}
}
#keyframes animateLogoOut {
from {stroke-dashoffset: 0px;}
to {stroke-dashoffset: -510px;}
}
And voila! You can find all of this and more on my codepen showing in detail the 2 options with an SVG logo hover animation.
https://codepen.io/MateoStabio/pen/jOVvwrM
Have tried several solutions here, nothing worked flawlessly; then Searched the web a bit more, to find GSAP at https://greensock.com/ (subject to license, but it's pretty permissive); once you reference the lib ...
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
... you can go:
var el = document.getElementById('divID');
// create a timeline for this element in paused state
var tl = new TimelineMax({paused: true});
// create your tween of the timeline in a variable
tl
.set(el,{willChange:"transform"})
.to(el, 1, {transform:"rotate(60deg)", ease:Power1.easeInOut});
// store the tween timeline in the javascript DOM node
el.animation = tl;
//create the event handler
$(el).on("mouseenter",function(){
//this.style.willChange = 'transform';
this.animation.play();
}).on("mouseleave",function(){
//this.style.willChange = 'auto';
this.animation.reverse();
});
And it will work flawlessly.
Try this:
#keyframe in {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#keyframe out {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
supported in Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

CSS opacity transition on page open

I want my CSS div to be completely invisible when page opens but after 2s appear on screen.
I tried setting opacity: 0; and then transition: opacity 100 2s; but it didn't work. I don't want CTA for example for it to happen after they hover or something but instead I want it to happen even if the user doesn't move the mouse. Please help!
You can use CSS animation to make it. Like this-
HTML-
<div class="div"></div>
And CSS-
<style>
.div{
width:100px;
height:100px;
background:red;
animation-name:opacity;
animation-duration:4s;
}
#keyframes opacity{
0%{opacity:0;}
100%{opacity:1;}
}
</style>
U can simply use CSS animations instead of transition.
consider HTML code having single div element
<div id="main"></div>
now to apply CSS animation we do something like this,
#main{
...add your desired code for styling the div...
animation-name:onload;
animation-duration: 1s;
animation-delay: 2s; //this is the key line, what this means is the animation would start after 2s of delay.
}
// Now creating animation
#keyframes onload{
0%{
opacity:0;
}
100%{
opacity: 1;
}
}

Css auto hide / show every 2s

I want to hide and show a div using css like :
Show => Hide => Show =>...
for do that I've tried that code:
#showMe {
animation: cssAnimation 0s 2s forwards;
visibility: hidden;
}
#keyframes cssAnimation {
to { visibility: visible;
}
}
but it will hide it only plz guys help!!
One way to do this is by adding keyframes for a specific progress (time-progress).
Some attributes in CSS are not animateable, so if you try to animate them they get instantly set to your "to" value, which is visible. To work around this, we simply set the visibility to hidden(in css) and keep it until 50% (in animation). At 51% we set it to visible, where it gets instantly shown (until the end).
To make it "blinking" you can repeat this animation by appending infinite which is a shorthand for animation-iteration-count: infinite.
#showMe {
animation: cssAnimation 1s infinite;
visibility: hidden;
}
#keyframes cssAnimation {
50% {
visibility: hidden;
}
51% {
visibility: visible;
}
}
<div id="showMe">(╯°□°)╯︵ ┻━┻</div>
Try to add property animation-iteration-count and set value it to infinite. It should play the animation infinite times.

Fade image on-load using css3

This is my code:
http://jsfiddle.net/NVk2N/2/
I'm trying to fade the large background image in. I tried this:
#cover {
background: url(http://bootstrapguru.com/preview/cascade/images/carousel/imageOne.jpg) no-repeat center center fixed;
background-size: cover;
height:100%;
width: 100%;
position:fixed;
opacity:0;
transition: opacity 2s;
}
however the image never appears. What am I doing wrong?
James
You actually need an animation of the opacity, in which you set animation-fill-mode: forwards so the last frame continues to apply after the final iteration of the animation.
Updated fiddle: http://jsfiddle.net/NVk2N/7/
#cover {
...
-webkit-animation: 2s show;
-moz-animation: 2s show;
-ms-animation: 2s show;
animation: 2s show;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
#-webkit-keyframes show {
from { opacity: 0 }
to { opacity: 1 }
}
#-moz-keyframes show {
from { opacity: 0 }
to { opacity: 1 }
}
#-ms-keyframes show {
from { opacity: 0 }
to { opacity: 1 }
}
#keyframes show {
from { opacity: 0 }
to { opacity: 1 }
}
(of course you need to use vendor prefixes where necessary)
Note: If you need to fade-in only the background image (and not the whole element) you could load the background inside an absolute positioned pseudoelement (e.g. #cover:before) with a negative z-index and just apply the animation to the psuedoelement itself:
Here's an example on codepen: http://codepen.io/anon/pen/EJayr/
Relevant CSS
#cover {
position: relative;
width : ...;
height : ...;
}
#cover:before {
content : "";
position: absolute;
z-index : -1;
top : 0;
left : 0;
width : 100%;
height : 100%;
background: url(...) top left no-repeat;
-webkit-animation: 5s show;
-moz-animation: 5s show;
-ms-animation: 5s show;
animation: 5s show;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
Animations on pseudoelements work fine on every modern browser (except in Chrome < 26 — as reported on issue #54699 — but not really a problem, since the current version at this moment is 34.0.1847.116)
you need to use some js code to trigger the animation property. just add a new class for #cover with opacity:1 and on body load assign this class to cover.
example
<body onload="document.getElementById('cover').classList.add('showed');">
To trigger a transition you actually need a trigger.
You are setting a opacity of "0" and this is what you get: 0 opacity.
The transition would work if the declaration of opacity would change from 0 to 1.
That is what transitions do.
The solution of Fabrizio Calderan with the Animation should do the job.
Working with the other answers that have been given will give you a fade on all the elements within that element so this will no achieve your desired result.
The best way to do this is to:
1) Create a div with a z-index of 1 which holds your background image and what you want to fade
2) Create another div with a z-index of 10 which holds your content which you dont want to fade and position it over the background div with position absolute.
3) Animate the background image with jquery animate
I hope this helps and that will give you your desired outcome!
I believe you may use keyframes and animations to get the job done.
It's not possible with purely css to fade only the background image. Reference: How to fade in background image by CSS3 Animation
The answer there explains that you may use <img> inside a <div> that you apply the fade animation on as there is no other way without anything but css.

Scroll To And Highlight Div When Link Is Clicked

I'm trying to highlight a div that wraps a contact form so the user knows where to go to contact. my link will be something like this
Contact Us
Going with a class since this will be used on the site in two places.
right now the current background for #form is #f5f5f5 so what I want to do is Flash a random color like #ff0000 and slowly fade it out back to #f5f5f5
demo on dabblet.com
Target pseudo­-class applied to element which you are scrolled to.
Add this to your css:
CSS:
#form {
background-color: #f5f5f5;
}
#form {
background-color: #f5f5f5;
}
#form:target {
animation: target-fade 1s 1;
}
#keyframes target-fade {
0% { background-color: #ff0000; }
100% { background-color: #f5f5f5; }
}
HTML markup:
link to target #form
<form id="form">
…
</form>
PS:
Accordingly to caniuse.com CSS properties: animation and keyframes is needed vendor prefixes such this:
.box_animation:hover {
-webkit-animation: myanim 1s infinite; /* value is demo only */
-moz-animation: myanim 1s infinite;
-o-animation: myanim 1s infinite;
animation: myanim 1s infinite;
}
#-webkit-keyframes myanim {…}
#-moz-keyframes myanim {…}
#-o-keyframes myanim {…}
#keyframes myanim {…}
PPS: dabblet using prefix free JS library to paste all necessary prefixes. Later without this library you can see all you need prefix syntax on css3please
You can use the Ariel Flesler's ScrollTo jQuery Plugin to scroll with animation.
And for changing color with animation you use the jQuery Color Animation Plugin
example
$('selector').scrollTo( '520px', 800 )
.animate({backgroundColor:'#ff0000'}, {duration:5000,queue:false});
Edits
If you want to fade it back you can use toggle function.
$('selector').scrollTo( '520px', 800 )
.toggle(function() {
$(this).animate({
{backgroundColor:'#ff0000'}, {duration:5000,queue:false});
},
function() {
$(this).animate({
{backgroundColor:'#f5f5f5'}, {duration:5000,queue:false});
});