Overriding animation-fill-mode: forwards in JavaScript/CSS - javascript

I have some text I am animating in, and I do so using CSS keyframes. I keep the look of the end result of the animation, so I'm using animation-fill-mode: forwards to do so, like this:
#my-text {
opacity: 0;
}
.show-me {
animation-name: show-me;
animation-duration: 2s;
animation-fill-mode: forwards
}
#keyframes show-me {
100% {
opacity: 1;
}
}
I then add the show-me class to the element using jQuery:
$('#my-text').addClass('show-me');
Later, after the animation is complete, I try to change the opacity of the element through code, but an unable to do so:
// this won't change the opacity, unfortunately
$('#my-text').css('opacity', 0);
Here's an example that shows the issue: http://jsfiddle.net/x3mbkbwL/2/
How do I override the value set from the animation when using fill-mode forwards? I know I can remove the class (in this case "show-me") when I need to change the element's opacity, but it seems like I should be able to directly override the css in JavaScript and it would override the opacity.

Seems like CSS attributes set by animation-fill-mode: forwards can't be overwritten on the same element.
Either: Add a parent wrapper around
One solution is to put a wrapper around the element that has animation-fill-mode: forwards set. Then, in order to overwrite forwarded attributes, you would only update the parent instead.
<div id="parent">
<div id="my-text">I just faded in!</div>
</div>
Then "overwrite" opacity only on the parent:
$('#parent').css('opacity', 0);
I've implemented the changes to your fiddle here: http://jsfiddle.net/x3mbkbwL/3/
Or: Nest a wrapper inside
If you prefer, you could alternatively add another child element instead:
<div id="my-text">
<span id="wrapper">I just faded in!</span>
</div>
Then "overwrite" opacity only on the nested wrapper:
$('#wrapper').css('opacity', 0);
Both approaches work best if the forwarded opacity is set to 1. If it's forwarded to 0 then it obviously won't work as the element is then already hidden.

Related

jQuery .fadeOut method on and element that is being appended after DOM load

(I am 9 weeks into a boot camp, so I apologize for the potentially rudimentary nature of this...)
I am appending an element to the DOM (a button) within a conditional:
$('.buttonsAndInputs').append(`<button id="clearHistoryButton">Clear All</button>`);
When this button is clicked, it runs through a series of functions to empty an array and clear some other content off the DOM. I would like to use the .fadeOut method of jQuery to remove THE BUTTON.
I have this in a subsequent function:
$('#clearHistoryButton').remove();
I would like to:
$('#clearHistoryButton').fadeOut(1000);
...so that it disappears in a fancy fashion.
It's not working - it simply waits one second and then - POOF - is gone.
This is my first question. This community has been ESSENTIAL in my growth in this realm and, as always, I appreciate all of you so very much.
Did you try transition: opacity 1s in your CSS ?
Advantage:
Hardware accelerated (GPU), i.e. it doesn't bother your main processor (CPU) with this task, whereas jQuery's fadeOut() function is software based and does take CPU resources for that effect.
Steps:
Add transition: opacity 1s to your CSS rules of the desired button element
here: ( #clearHistoryButton )
Add a CSS rule with button.fadeMeOut with opacity: 0
Add a simple jQuery function to add the class ".fadeMeOut" at click
Then remove button with setTimeout(function(){$('#clearHistoryButton').remove()},1000)
Run code snippet
$(function() { // Shorthand for $( document ).ready()
$("#clearHistoryButton").on( "click", function() {
// first: fade out the button with CSS
$(this).addClass("fadeMeOut");
// then: after fadeOut effect is complete, remove button from your DOM
setTimeout(function(){
$('#clearHistoryButton').remove();
},1000);
});
});
button {
opacity: 1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
}
button.fadeMeOut {
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="clearHistoryButton">Press to hide me</button>

Apply a animation to an HTML Tag with Javascript on Clickevent

:D
I got akey frame and i want to apply the animation it to the body when button is clicked
document.getElementById('button2').addEventListener('click', infos2)
function infos2 () {
document.getElementsByTagName("body").style = "body{animation:rotate-scale-up .2s linear infinite both}";
}
well my JS dosent work obviously :D Any Idea?
Welcome to Stackoverflow.
The problem here is that the style you apply here is invalid.
Your style should be applied like this:
document.getElementsByTagName("body")[0].style.animation = "rotate-scale-up .2s linear infinite both";
getElementsByTagName returns an array of objects, therefore you have to insert [0] to select the first element in that array to make it work correctly.
You can also use document.body instead.
If you apply a style directly on a HtmlObject like the body, the style will expicitly be set on this element. You don't need a 'body' selector in this case.
Plus: You need an imported stylesheet or a style tag in the page, where the animation-keyframes of rotate-scale-up are defined. It's not obvious if you already done that or not.
Something like:
<style>
#keyframes rotate-scale-up{
0% { transform: scale(.1) rotate(0deg)}
100% { transform: scale(1) rotate(360deg)}
}
</style>
Otherwise you page will not know what rotate-scale-up is.

Wait for class to be added before modifying styles

I'm trying to do something like this:
element.classList.add('animate-in')
element.style.transform = 'translateY(100px)';
Where the animate-in class has a transition: transform 1s property for animation. But when I run this it the element is translated 100px down but without the transition, seems like the transform property is modified before the class name can be added and take affect. I don't want to use setTimeout since it can be unreliable in animations. Is there any way to wait for the class to be added before modifying any styles?
I don't think we get any events for the 'application of styles' through JavaScript, which is pretty frustrating in this case...
I found this thread that's pretty helpful.
One thing to note: the animation will work even if you use setTimeout with 0 ms. What was the reason in particular that it messed with animations?
setTimeout(function(){
element.style.transform = 'translateY(100px)'
}, 0)
Also, if you set it up with an event, you can change the style directly and see the animation applied.
Here's the bin I was playing around with: https://jsbin.com/lofotutumu/edit?html,css,js,output
You don't really want to wait, but want the properties embedded with this new class to be applied.
And this can be done, synchronously, by triggering a reflow.
Some properties/functions need the DOM boxes to be recalculated in order to return their values. To do so, the browser has to trigger a reflow on the page, and hence will apply your new properties.
But note that this has a performance impact, particularly on complex pages, so use it with care.
element.classList.add('animate-in');
element.offsetTop; // trigger a reflow
element.style.transform = 'translateY(100px)';
.animate-in {
transition: transform 2s linear;
}
<div id="element">Hello</div>
Would creating a keyframe and adding that into your class suit your needs? E.g.
// This is your keyframe to animate your element
#keyframes translateDown {
0%{
transform:translateY(0);
}
100%{
transform:translateY(100px);
}
}
.animate-in{
animation: 2s linear translateDown both;
}

CSS animation causing z-index problems

I have a weird conflict in my main.js file. I run a fade up animation on ".main-headline--left"
$('.main-headline--left').addClass('wow animated fadeInUp');
This works fine, but when I add a piece of code that makes nav-links active based on what page the user is on, the animation obstructs the logo which hangs off of the navbar (logo height > navbar fixed height). Here is that code:
if(location.pathname != "/") {
$('.navbar-nav--split a[href^="/' + location.pathname.split("/")[3] + '"]').addClass('is-active');
} else $('.navbar-nav--split a:eq(0)').addClass('is-active');
I notice this only happens in Chrome. Is there perhaps a better way to organize my Javascript or a better way to write the code so that this problem is rectified?
Here is the css animation:
#keyframes fadeInUp {
0% {
opacity: 0;
transform: translateY(30px);
transition: .1s transform, .1s opacity;
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
I did not explicitly set z-index on containing elements. However, setting a z-index of 9999 on both the logo navbar does not fix the problem.
today I ran into similar issue... I patched it by changing the value of animation-fill-mode for the class animated as below...
.animated
{
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: initial; //Changed from both to initial
animation-fill-mode: initial; /*Changed from both to initial
}
Notably, setting the animation-fill-mode to forwards was causing my issue...
animation-fill-mode: both inherits both forwards as well as backwards property, so my trillionth z-index element got hid under the millionth z-index element...
Setting it to initial worked for me.
I found a fix to my problem, but I have no idea why this solution works. By adding "-webkit-backface-visibility: hidden;" to my logo element, my logo no longer gets cropped when the animation on my headline and the transition on my anchor's pseudo element are run on load. I was wondering whether anyone knows why this would fix this problem. My logo element never moves on the z axis. There is a jsfiddle in the comment section that shows the code
#GughaG's answer is right if don't need forwards, but if you do need, try adding position: absolute -- fixed me right up!
The answers here did not initially make it clear that the transformed elements cannot be siblings of each other and still retain z-index layering. Therefore, a top, middle and bottom layer animating would flip/flop all over each other and other elements in the page, for example a modal popup.
What needs to happen is a wrapping control layer that is not animated but holds the z-index order of things.
i.e. from this:
<wrapper>
<child-1 /> <- animated element bottom layer
<child-2 /> <- animated element middle layer
<child-3 /> <- animated element top layer
</wrapper>
To this:
<wrapper>
<child-wrapper-1>
<child-1 /> <- animated element bottom layer
</child-wrapper-1>
<child-wrapper-2>
<child-2 /> <- animated element middle layer
</child-wrapper-2>
<child-wrapper-3>
<child-3 /> <- animated element top layer
</child-wrapper-3>
</wrapper>
Where child-wrapper 1 has z-index of 1, child-wrapper 2 has z-index of 2 etc. and are NOT animated.
Here is a working fiddle: https://jsfiddle.net/pingram3541/8rdx9u2w/show

How to correctly wait until JavaScript applies inline Css

I have this jsFiddle. When the button is clicked, I want to put the red div behind the black one immediately, then start the animation.
var red = document.getElementById("red");
var button = document.getElementById("button");
button.addEventListener("click",function () {
red.style.zIndex = -1;
red.classList.remove("shifted");
});
However, as you can see, they seem to be occurring as two separate actions. I know I can use setTimeout to wait until the zIndex property is applied, but I do not know how long I am supposed to wait, and the duration perhaps differs from browsers to computers.
Should I create a loop that will check if zindex was applied? But this also sounds like an unintelligent solution. What is the correct way?
EDIT: I do not want to change the zIndex on the black div.
You can bind to the transitioned state of the element, something like this:
("#mySelector").bind("transitionend", function(){ 'yourcodehere' });
Also, here is some info on it:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
https://developer.mozilla.org/en-US/docs/Web/Reference/Events/transitionend
Without jQuery:
el.addEventListener("transitionend", updateTransition, true);
Edit:
There was some confusion as to the usage of:
-webkit-transition-duration: 1s;
This is applied like a styling as well. So anytime you make alterations to the element it is on, you are triggering this. You have TWO transition calls, one for setting the z-index, another for the movement.
Just put a
-webkit-transition-property: -webkit-transform;
into the #red and everything is fine. ;) This applies the transition only to specified property.
JSFIDDLE: http://jsfiddle.net/Qvh7G/.
The problem is with zIndex - the transform time delays the change in the zIndex.
You can simply force the duration for the transform property.
Replace:
-webkit-transition-duration: 1s;
With
-webkit-transition: -webkit-transform 1s; // ease-in;

Categories