Update 2019-12-18 with better solution
See other SO question with updated solution Trigger CSS transition on appended element
Short version: wrap the adding of a CSS animation class in a JS block that forces the browser to re-render the flow and not optimize it into a single call.
# CSS animation class
.visible {
...styles to change transparency from 0 -> 1
...styles to transform(scale) from 0.8 -> 1.0
}
# JS code
requestAnimationFrame(() => {
this.element.classList.add("visible")
})
Previously I had to do something like this:
$element.hide().show()
$element.addClass("visible")
Original question
I'm building an overlay (background for modals or dialog boxes) and I want it to fade in when I create the element. I do the animation by adding/removing a .visible
class to the element using CSS3 transitions.
# SASS styles
.overlay {
background-color: rgba(0, 0, 0, 0.6);
cursor: pointer;
height: 100%;
left: 0;
position: fixed;
pointer-events: none;
top: 0;
width: 100%;
will-change: opacity;
@include transparency(0);
@include transition(opacity 0.3s cubic-bezier(0, 0, 0.3, 1));
&.visible {
pointer-events: auto;
@include transparency(1.0);
}
}
When the overlay element already exists on the DOM, everything works just fine:
$(".overlay").addClass("visible") # => does animation as expected...
However, when I CREATE the element and THEN try to animate it, it does not:
# JavasScript using jQuery
tag = $("<div class='overlay'></div>")
$("body").append(tag)
tag.addClass("visible")
I understand this is because the JavaScript is creating and adding the class "instantly", so what I have to do is this:
tag = $("<div class='overlay'></div>")
$("body").append(tag)
tag.hide()
tag.show()
tag.addClass("visible")
By "hiding" and then "showing" the element, it has enough time for the add class to animate the element.
Question This seems pretty hacky to show/hide an element so I can then animate it via CSS transitions. Is there a cleaner way of implement this?