0

Is there a way to get notified, after inserting an element into the DOM with insertBefore(), when this element becomes actually visible/available to user ? Especially to start applying CSS transforms on it ?

Complete problem

Forgive me if this question is recurrent, I didn't find a suitable answer so far. I'm trying to implement a custom popup dialog system on a website of my own, similar to SweetAlert or some other products.

I would like to apply some special effects when this popup shows up, such as a progressive darkening of the background, as well as a slow vertical motion on the box itself.

To achieve all of this, I spawn one big, fixed div element covering the whole screen (the background) and containing the popup box. When I need it, I first insert this element as body's first child, tagging it with a special invisible class. Once inserted, I remove this invisible class from the element and let the CSS rules do the magic.

The problem is that even if removed the class after having inserted this element, this one will be rendered only when the Javascript function leaves, hence directly in its final state.

When doing this on a complete initial page, the load event helps. I now would like to do the same on an existing page.

As always, I'm interested on both solutions to this (potentially XY) problem: if there's a better way to do it, I'll be happy to discover it, but I'm still interested in solving this particular situation anyway.

Thanks in advance to everyone.

EDIT: currently performing tests on Firefox 82.0.2

Obsidian
  • 3,719
  • 8
  • 17
  • 30
  • 4
    Sounds like you may want to have a look at the [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) approach. – Mike 'Pomax' Kamermans Oct 26 '21 at 19:41
  • 1
    Sounds like you need to add a slight delay to when you remove the class. – epascarello Oct 26 '21 at 19:45
  • 1
    https://stackoverflow.com/questions/1462138/event-listener-for-when-element-becomes-visible – F4st3r Oct 26 '21 at 19:51
  • @epascarello : this is actually what I do as a "temporary workaround" but I'd like to do better ;-) – Obsidian Oct 26 '21 at 19:56
  • @Mike & F4ster : thanks a lot ! "Mutation Observer" and former "Mutation Event" seem to be the keywords I was missing. Could you redact a small answer so I can validate it and close the entry ? Cheers. – Obsidian Oct 26 '21 at 19:56
  • Seems odd you need to remove the class to get the animation to show up. Maybe it is just an issue with your CSS? – epascarello Oct 26 '21 at 20:05
  • I've actually spoken too fast. MutationObserver works, but the result is the same. I get no animation without delaying it with setTimeout() or something. :-( – Obsidian Oct 26 '21 at 20:11
  • @epascarello : I could have "added" the class instead, the problem will be the same. I chose to remove it simply to have my document freed from any temporary feature when in its final state. Also, the CSS works fine when adding the class manually or through a setTimeout() operation. – Obsidian Oct 26 '21 at 20:13
  • 1
    Are you using `transition`? Might want to go with keyframes if that is the case. – epascarello Oct 26 '21 at 20:16
  • @epascarello : many thanks ! I used keyframes in the past for some another projet and I just didn't think about it at the time. I just tried and since, indeed, there's no transition case, animation is honored. Could you write a small answer to officially suggest it ? – Obsidian Oct 26 '21 at 21:41

1 Answers1

0

Thanks to comments above, here's a valid solution to both exposed problems:

  • "Mutation Observer", as well as former "Mutation Events" (now deprecated) are the best way to get notified when something is inserted. It won't help with animations issues, though, because it's still not guaranteed to be rendered yet at this time ;
  • Rather than applying a class then another to perform a transition, it's better to define a regular animation using @keyframes that plays only once. It's guaranteed to be played when the object appears, by definition.

Many thanks to "Pomax", F4st3r and epascarello for their help.

Obsidian
  • 3,719
  • 8
  • 17
  • 30