CSS transitions do not work when assigned trough JavaScript
To make transition
work, three things have to happen.
- the element has to have the property explicitly defined, in this case:
opacity: 0;
- the element must have the transition defined:
transition: opacity 2s;
- the new property must be set:
opacity: 1
If you are assigning 1 and 2 dynamically, like you are in your example, there needs to be a delay before 3 so the browser can process the request. The reason it works when you are debugging it is that you are creating this delay by stepping through it, giving the browser time to process. Give a delay to assigning .target-fadein
:
window.setTimeout(function() {
slides[targetIndex].className += " target-fadein";
}, 100);
Or put .target-fadein-begin
into your HTML directly so it's parsed on load and will be ready for the transition.
Adding transition
to an element is not what triggers the animation, changing the property does.
// Works
document.getElementById('fade1').className += ' fade-in'
// Doesn't work
document.getElementById('fade2').className = 'fadeable'
document.getElementById('fade2').className += ' fade-in'
// Works
document.getElementById('fade3').className = 'fadeable'
window.setTimeout(function() {
document.getElementById('fade3').className += ' fade-in'
}, 50)
.fadeable {
opacity: 0;
}
.fade-in {
opacity: 1;
transition: opacity 2s;
}
<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>
Disabling and enabling css transition to initialize position
Adding a timeout to the addClass :
function onThumbnailClick(event) {
var index = parseInt(event.target.id.split('-')[1]);
initPortraitPanel(index);
$('.portraitDiv').setTimeout(addClass('active-transition'), 50);
}
codepen
Seems that this was already answered , downvoted, and deleted ... I don't know why
css3 transitions not firing first time in Firefox 4
Set left: 0
in your styles for ul
; that got it working in the fiddle for me: http://jsfiddle.net/ctY68/4/
Looks like Gecko isn't considering your first style change a transition because there was no initial value set.
CSS transition doesn't start/callback isn't called
For a comprehensive explanation of why this happens, see this Q/A, and this one.
Basically, at the time you set the new style
the browser still has not applied the one set inline, your element's computed style still has its display
value set to ""
, because it's what elements that are not in the DOM default to.
Its left
and top
computed values are still 0px
, even though you did set it in the markup.
This means that when the transition
property will get applied before next frame paint, left
and top
will already be the ones you did set, and thus the transition will have nothing to do: it will not fire.
To circumvent it, you can force the browser to perform this recalc. Indeed a few DOM methods need the styles to be up to date, and thus browsers will be forced to trigger what is also called a reflow.Element.offsetHeight
getter is one of these method:
let tablehtml = `
<div id="spanky"
style="position: absolute;
left: 10px;
top: 10px;
background-color:blue;
width:20px;
height:20px;
transition: left 1000ms linear 0s, top 1000ms linear 0s;">
</div>`;
document.body.innerHTML += tablehtml;
let animdiv = document.getElementById('spanky');
animdiv.addEventListener("transitionend", function(event) {
animdiv.style.backgroundColor='red';
}, false);
// force a reflow
animdiv.offsetTop;
// now animdiv will have all the inline styles set
// it will even have a proper display
animdiv.style.backgroundColor='green';
Object.assign(animdiv.style, {
left: "100px",
top: "100px"
});
Clean way to programmatically use CSS transitions from JS?
There isn't a clean way at this moment (without using CSS Animations -- see the nearby answer by James Dinsdale for an example using CSS Animations). There is a spec bug 14617, which unfortunately wasn't acted upon since it was filed in 2011.
setTimeout
does not work reliably in Firefox (this is by design).
I'm not sure about requestAnimationFrame
-- an edit to the original question says it doesn't work reliably either, but I did not investigate. (Update: it looks like requestAnimationFrame
is considered at least by one Firefox core developer to be the place where you can make more changes, not necessarily see the effect of the previous changes.)
Forcing reflow (e.g. by accessing offsetHeight
) is a possible solution, but for transitions to work it should be enough to force restyle (i.e. getComputedStyle
): https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/
window.getComputedStyle(elem).opacity;
Note that just running getComputedStyle(elem)
is not enough, since it's computed lazily. I believe it doesn't matter which property you ask from the getComputedStyle, the restyle will still happen. Note that asking for geometry-related properties might cause a more expensive reflow.
More information on reflow/restyle/repaint: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
Change of opacity using css transition and vanilla JavaScript works only when fading out
This should work , Code pen link: http://codepen.io/saa93/pen/gLbvmQ
You would need to add this instead of directly setting opacity to 1
// Show button by increasing opacity
buttonElement.style.opacity = 0;
setTimeout(() => {
buttonElement.style.opacity = 1;
}, this.animationDelay + 20);
Related Topics
Polymer Share Styles Across Elements
Repeat Animation Every 3 Seconds
Span Inside Button, Is Not Clickable in Firefox
Is "Monkey Patching" Really That Bad
Mocha/Chai Expect.To.Throw Not Catching Thrown Errors
Rotate the Elements in an Array in JavaScript
State Not Updating When Using React State Hook Within Setinterval
Last Segment of Url with JavaScript
Fastest Method to Replace All Instances of a Character in a String
Why Is Element Not Being Shown Before Alert
Can't Change Border Color of Material-Ui Outlinedinput
Rails 4 Turbolinks Make Form Submit Multiple Times
Firing a Keyboard Event in Safari, Using JavaScript