Trigger CSS Transition on Appended Element

Trigger CSS transition on appended element

The cause of not animating the newly added element is batching reflows by browsers.

When element is added, reflow is needed. The same applies to adding the class. However when you do both in single javascript round, browser takes its chance to optimize out the first one. In that case, there is only single (initial and final at the same time) style value, so no transition is going to happen.

The setTimeout trick works, because it delays the class addition to another javascript round, so there are two values present to the rendering engine, that needs to be calculated, as there is point in time, when the first one is presented to the user.

There is another exception of the batching rule. Browser need to calculate the immediate value, if you are trying to access it. One of these values is offsetWidth. When you are accessing it, the reflow is triggered. Another one is done separately during the actual display. Again, we have two different style values, so we can interpolate them in time.

This is really one of very few occasion, when this behaviour is desirable. Most of the time accessing the reflow-causing properties in between DOM modifications can cause serious slowdown.

The preferred solution may vary from person to person, but for me, the access of offsetWidth (or getComputedStyle()) is the best. There are cases, when setTimeout is fired without styles recalculation in between. This is rare case, mostly on loaded sites, but it happens. Then you won't get your animation. By accessing any calculated style, you are forcing the browser to actually calculate it.

CSS transition not working after element is appended

The "list" variable is a jQuery object, but the elements you pull out of it as "target" are not jQuery objects - they're the DOM nodes. Thus your calls to ".css()" are failing (which is reported in the error console for me).

Once you've fixed that, then the next thing is the issue of how the browser deals with a sequence of CSS updates. It's not clear to me what exactly I'm seeing (from Firefox 18 on Linux), but I think the basic issue is that because no layout reflow is done between the changes, the net effect is that the styles are "collapsed" so that there's no net change.

In this update to the fiddle I took a different approach. I put the transition rules in the "box" class, and then added a "prefade" class:

.prefade {
transition-duration: 0;
opacity: 0;
}

Then, instead of messing with the element style, I add "prefade" before appending, and then trigger a layout update by asking for the element's offset. Then I can remove the "prefade" class, and the box fades in.

target.addClass('prefade');
// Put it on top
container.append(target);

var p = target.offset();

target.removeClass('prefade');

I don't know whether that's the "right" way to do things. edit — to make it work in Chrome, the "transition" properties need to be repeated with the -webkit- prefix.

css transitions on new elements

requestAnimationFrame() (https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) appears to work across Firefox, Chrome and Safari. A more reliable, logical solution that setTimeout(). For older browsers (IE8), it will require a Polyfill (naturally, the transition won't occur, but the CSS will still change).

How to appendChild with Animation in javascript?

To append images sequentially you can do:

  • use JS's .forEach(element, index) that:
  • creates a random image
  • appends the image to DOM
  • use setTimeout(()=> {/*job*/}, time * index ) where time*index will result in N timeouts like: 0, 500, 1500 .... having time set to 500ms and the job is to add your .animate class.

const images = [  "//placehold.it/300x300/0bf",  "//placehold.it/300x300/f0b",  "//placehold.it/300x300/bf0",  "//placehold.it/300x300/0fb",  "//placehold.it/300x300/b0f",  "//placehold.it/300x300/fb0",];
const createImg = (el, i) => { const img = document.createElement("img"); img.src = images[~~(Math.random() * images.length)]; el.appendChild(img); setTimeout(()=> img.classList.add("animate"), i*500);}

document.querySelectorAll(".result").forEach(createImg);
body {  display: flex;}
.result img{ max-width: 100%; transform: scale(0); transition: 0.5s;}
.result img.animate{ transform: scale(1);}
<div class="result"></div><div class="result"></div><div class="result"></div>

Creating HTML element and animating after creation

"Cleaner" is in the eye of the beholder, but one simple way is to wait a tick before you add the visible class:

$("body").append(tag);
setTimeout(function () {
tag.addClass("visible");
}, 0);

That'll wait until the appending is complete before adding the class. You might need to adjust the 0 value higher.

CSS delayed visibility transition doesn't trigger JavaScript transitionend event for visibility?

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/transitionend_event:

If there is no transition delay or duration, if both are 0s or neither is declared, there is no transition, and none of the transition events are fired.

transition: visibility 0s ease-in-out 3s

Your transition-duration for visibility is 0s here.

Make that .0001s, and you'll see the transitionend event for visibility fire as well.



Related Topics



Leave a reply



Submit