How to prevent CSS animation on page load? - css

I have an animation, which is taking care of the fading in and out transition on button hover state.
The problem is that the default animation (-webkit-animation: off-state 1s;) is firing off on page load. How do I make it active only after first hover state?
I know how to achieve this using CSS transitions. I am looking for a solution using animation/keyframes.
HTML
<div class="button"></div>
CSS
.button { background: #000; width: 20px; height: 20px; -webkit-animation: off-state 1s; }
.button:hover { -webkit-animation: on-state 1s; }
#-webkit-keyframes on-state {
0% { height: 20px; }
100% { height: 100px; }
}
#-webkit-keyframes off-state {
0% { height: 100px; }
100% { height: 20px; }
}
Demo

As suggested by #Zeaklous, this can be done using JavaScript, e.g. using jQuery:
$('.button').one('mouseout', function () { $(this).addClass('alt-animation'); });
and moving the animation rule to .alt-animation class:
.button { background: #000; width: 20px; height: 20px; }
.button.alt-animation { -webkit-animation: off-state 1s; }
.button:hover { -webkit-animation: on-state 1s; }
Ideally, there should be CSS only alternative.

Related

I'm trying to Animate from bottom by CSS but isn't working

I'm trying to have a span appear from the bottom by css I wrote the following code that'snot working,
span {
display: inline !important;
background-color: transparent !important;
overflow: hidden;
animation: from-btm 1s !important;
#keyframes from-btm {
from {
margin-bottom: -5%;
}
to {
margin-bottom: 0%;
}
}
}
Use position: relative and bottom for the animation positioning (margin-bottom won't apply to an inline element). The overflow: hidden needs to be on a parent container and the keyframes rule needs to be outside the CSS rule for the span:
span {
position: relative;
display: inline !important;
background-color: transparent !important;
animation: from-btm 1s !important;
}
#keyframes from-btm {
from {
bottom: -80%;
}
to {
bottom: 0%;
}
}
.container {
background: yellow;
overflow: hidden;
}
<div class="container">
<span>The Span</span>
</div>
There are two issues in your code. First, the span has to be inline-block secondly keyframes are to be declared outside span selector in CSS.
span {
display: inline-block !important;
background-color: transparent !important;
overflow: hidden;
animation: from-btm 1s !important;
}
#keyframes from-btm {
from {
margin-bottom: -5%;
}
to {
margin-bottom: 0%;
}
}
<span>ABCD</span>
Working Fiddle code
You need to write your keyframe outside of your style. It should be like that:
span {
display: inline !important;
background-color: transparent !important;
overflow: hidden;
animation: from-btm 1s !important;
}
#keyframes from-btn {
0% {
margin-bottom: -5%;
}
100% {
margin-bottom: 0%;
}
}
Your #keyframes property should be outside the span element. It should stay outside the span element because it is it's own element. Like This:
span {
display: inline !important;
background-color: transparent !important;
overflow: hidden;
animation: from-btn 1s ease 0s 1;
}
#keyframes from-btm {
from {
margin-bottom: -5%;
}
to {
margin-bottom: 0%;
}
}
Also you animation shorthand is not "that properly written" it should be animation: "animation-name" "animation-duration" "animation-display(ease, ease-in, ease-out, linear)" "animation-delay" animation-count(any number or even infinite); as seen above.
Also for performance reasons you should consider animate the position using the transform element like this: eg.
#keyframes from-btm {
from {
transform: translateY(200%);
}
to {
transform: translateY(10%);
}
}
Also when using transform make sure to add a position propery to your element span for example position: absolute or position: relative

Start CSS animation with on set of key frames then then loop another set of keyframes

I am trying to get an object to lead in with one CSS animation key frame set and then have it loop another key frame set forever. Is this possible?
Depends on what you are willing to do for it :)
I don't think that there is a solution to trigger the second animation from within the last keyframe of the first animation.
A possible solution would be to delay the second animation until the first one has finished like this:
#test {
height: 50px;
width: 50px;
background: grey;
animation: 2s firstAnimation forwards, 1s secondAnimation 2s alternate infinite;
/* the "2s" after "secondAnimation" is for the delay */
}
#keyframes firstAnimation {
100% {
width: 100px;
background: red;
}
}
#keyframes secondAnimation {
0% {
height: 50px;
}
100% {
height: 100px;
}
}
<div id="test"></div>
Another possible approach is to verify with javascripts onanimationend and then add the second animation by adding a class for example:
let test = document.getElementById("test")
test.onanimationend = function(event) {
console.log(event) // contains a lot of interesting infos like the name of the animation that ended :)
test.classList.remove("startFirstAnimation")
test.classList.add("startSecondAnimation")
}
#test {
height: 50px;
width: 50px;
background: grey;
}
.startFirstAnimation {
animation: 2s firstAnimation forwards;
}
#keyframes firstAnimation {
100% {
width: 100px;
background: red;
}
}
.startSecondAnimation {
width: 100px !important; /* cheating a little bit here to keep the state of the end of the firstAnimation... */
background: red !important;
animation: 1s secondAnimation alternate infinite;
}
#keyframes secondAnimation {
0% {
height: 50px;
}
100% {
height: 100px;
}
}
<div id="test" class="startFirstAnimation"></div>

How can I add two transition transforms but one after one?

I want to add 2 transition transforms
But I want to start the second transform after the end of the first transform
the element should go to a point slowly and after that it should go to another point
transform: translate(0%, 300%), translate(15%, -136%);
You cannot do this with just a single element using transition because when you put more than one translate within the transform, the transform property on the whole is transitioned and not one by one.
With pure CSS transition using an extra wrapper element:
If you add an extra wrapper element around the actual element and put one of the transforms on the wrapper element you could achieve the effect that you are looking for. It would also produce the exact reverse effect on the hover out (hover the body and hover out in the below snippet).
.wrapper {
position: relative;
height: 100px;
width: 100px;
transition: all 1s 1s;
}
.content {
position: absolute;
height: 100%;
width: 100%;
border: 1px solid;
transition: all 1s;
}
body:hover .content {
transform: translate(15%, -136%);
transition: all 1s 1s;
}
body:hover > .wrapper {
transform: translate(0%, 300%);
transition: all 1s;
}
body {
min-height: 100vh;
}
<div class='wrapper'>
<div class='content'>Some text</div>
</div>
Transition with a bit of JS/jQuery without any extra elements:
If you add an extra wrapper element around the actual element and put one of the transforms on the wrapper element you could achieve the effect that you are looking for. It would also produce the exact reverse effect on the hover out (hover the body and hover out in the below snippet).
$(document).ready(function() {
var isHover; /* variable to track state */
$('body').hover(function() {
isHover = !isHover; /* invert the state */
$('.content').css('transform', 'translate(0%, 300%)');
}, function() {
isHover = !isHover; /* invert the state */
$('.content').css('transform', 'translate(0%, 300%)');
});
$('.content').on('transitionend', function() {
if (isHover) {
$('.content').css('transform', 'translate(0%, 300%) translate(15%, -136%)');
} else {
$('.content').css('transform', 'none');
}
});
});
.content {
height: 100px;
width: 100px;
border: 1px solid;
transition: all 1s;
}
body {
min-height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='content'>Some text</div>
With animation and no extra element:
Using animations this can be done using a single element but the reverse effect is tough to achieve. We would have to write extra code for this and even then it will be complex.
.content {
position: relative;
height: 100px;
width: 100px;
border: 1px solid;
}
body:hover > .content {
animation: move 1s forwards;
}
#keyframes move {
0% {
transform: none;
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: translate(0%, 300%) translate(15%, -136%);
}
}
body {
min-height: 100vh;
}
<div class='content'>Some text</div>
Animations with reverse effect:
Below is a snippet which produces the reverse effect also using CSS animations. But as you can see it is a bit complex. We can do this using a single animation also but it would become more complex.
$(document).ready(function() {
$('body').hover(function() {
$('.content').css('transform', 'none');
$('.content').removeClass('hover-out').addClass('hover-in');
}, function() {
$('.content').css('transform', 'translate(0%, 300%) translate(15%, -136%)'); /* as soon as an animation is removed, the element would snap back to original state, to avoid that we have to add final state via inline style */
$('.content').removeClass('hover-in').addClass('hover-out');
});
});
.content {
height: 100px;
width: 100px;
border: 1px solid;
}
.hover-in {
animation: hover-in 1s forwards;
}
.hover-out {
animation: hover-out 1s forwards;
}
#keyframes hover-in {
0% {
transform: none;
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: translate(0%, 300%) translate(15%, -136%);
}
}
#keyframes hover-out {
0% {
transform: translate(0%, 300%) translate(15%, -136%);
}
50% {
transform: translate(0%, 300%);
}
100% {
transform: none;
}
}
body {
min-height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='content'>Some text</div>

Animation delay on CSS3 keyframe with just CSS?

I was discussing with someone the ability for CSS3 to do animations upon click and hover and I decided to make a little test to show them. I decided to do a bit of boundary pushing and made it so that when you hovered over the animation happened, and when you un-hovered it waited 3 seconds and then ran the animation to put it back.
The problem however is that when the page loads, it runs the "un-hover" animation.
Any ideas for getting around this or another method that's better?
What the below code does is when you hover over the red box it animates is blue. When you un-hover is animates it back red again after 3 seconds. Both of them calculate to a 1 second animation time.
I know this could be fixed with one very simple line of JavaScript, but I'm only interested in seeing if there's a CSS answer.
#-webkit-keyframes makeblue {
0% {
background: red;
}
100% {
background: blue;
}
}
#keyframes makeblue {
0% {
background: red;
}
100% {
background: blue;
}
}
#-webkit-keyframes makered {
0% {
background: blue;
}
75% {
background: blue;
}
100% {
background: red;
}
}
#keyframes makered {
0% {
background: blue;
}
75% {
background: blue;
}
100% {
background: red;
}
}
div {
width: 100px;
height: 100px;
background: red;
position: relative;
-webkit-animation: makered 4s;
animation: makered 4s;
}
div:hover {
-webkit-animation: makeblue 1s;
animation: makeblue 1s;
background: blue;
}
<div></div>
EDIT 1
Does anyone know if this type of functionality exists, or even potentially planned for the future?:
#keyframes makeblue {
0% {
background: [CurrentValue];
}
100% {
background: blue;
}
}
Having this would be able to fix the problem. If this doesn't exist, I think it should :).
If you are dealing with background or simple css only (not a keyframe animation), you can have it with transition delay, check it out at jsfiddle!:
div {
width: 100px;
height: 100px;
background-color: red;
position: relative;
transition:background-color 0.25s 3s linear;
}
div:hover {
background-color:blue;
transition:background-color 0.25s linear;
}

CSS3 Transition Fill Mode

Is there any way / trick to have transition keeping its state just like animation-fill-mode?
<style>
#firstdiv {
width: 100px;
height: 100px;
background: red;
animation: firstdivframe 2s;
animation-play-state: paused;
animation-fill-mode: forwards;
}
#firstdiv:hover {
animation-play-state: running
}
#keyframes firstdivframe {
from { background: red; }
to { background: yellow; }
}
#seconddiv {
width: 100px;
height: 100px;
background: red;
transition: background 2s;
}
#seconddiv:hover {
background: yellow;
}
</style>
<div id="firstdiv"></div>
<br />
<div id="seconddiv"></div>
jsbin
Based on above code, I want the seconddiv to behave just like firstdiv without using any javascript code. The firstdiv will keep its state when the mouse stops hovering or the animation ends, while the seconddiv will always go back to its original state.
No it is not possible to use transitions for this. CSS transitions will only transition between styles (hence the name). If you want to keep a state you have to added a class, for which you always need JavaScript.
I think that this is what your are looking for
#firstdiv {
width: 100px;
height: 100px;
background: red;
animation: firstdivframe 2s;
animation-play-state: paused;
animation-fill-mode: forwards;
}
#firstdiv:hover {
animation-play-state: running
}
#keyframes firstdivframe {
from { background: red; }
to { background: yellow; }
}
#seconddiv {
width: 100px;
height: 100px;
background: red;
animation: seconddiv 2s;
animation-play-state: paused;
animation-fill-mode: forwards;
}
#seconddiv:hover {
animation-play-state: running
}
#keyframes seconddiv {
from { background: red; }
to { background: yellow; }
}
ckeck if it works: jsbin
Please tell me if this is what you are looking for and then i will provide you a more "best-technic" solution with an explanation in each line. (i cannot currently comment).
Yes, of course! Think about setTimeout! You can use setTimeout with the same duration as you have in transition! And the call-back function of setTimeout should set the back the style that you want to keep it!

Resources