Mastering Enter/Exit Animations with Sandal SCSS Mixins and ES6
This tutorial explains how to implement enter and exit animations using Sandal's SCSS mixins and an ES6 JavaScript class, covering mixin usage, generated CSS, customizable parameters, and practical usage examples for seamless UI effects.
This tutorial series provides a practical guide to implementing enter and exit animations using the Sandal UI framework and Sheral UI, originally published on imweb, w3cplus, and the “Frontend Talk” WeChat channel.
Enter/Exit Animations
In _animation.scss six basic animation groups are defined (fade‑in/out, shrink‑in/out, up‑in/out, down‑in/out, left‑in/out, right‑in/out). The example below shows how to use the fade‑in/out mixins.
@include animation-fade-in;
@include animation-fade-out;The compiled CSS for the fade animations is:
.fade-in, .fade-out {
-webkit-animation-duration: 0.3s;
animation-duration: 0.3s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.fade-in {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
@-webkit-keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
.fade-out {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
}
@-webkit-keyframes fadeOut {
0% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes fadeOut {
0% { opacity: 1; }
100% { opacity: 0; }
}The mixins accept two optional parameters: animation-fade-in($className: fade, $from: 0), animation-fade-out($className: fade, $to: 0), where the first sets the class name (automatically appending “‑in” or “‑out”) and the second defines the start or end opacity.
ES6 Encapsulated Animation Class
export class AnimateInOut {
constructor({ele, className, inCallback, outCallback}) {
this.ele = ele.nodeType === 1 ? ele : document.querySelector(ele);
this.inClass = className + '-in';
this.outClass = className + '-out';
this.inCallback = inCallback;
this.outCallback = outCallback;
this.animationend = this.whichEndEvent();
this.endBind = this.end.bind(this);
}
// Enter
enter() {
this.ele.classList.add(this.inClass);
this.ele.addEventListener(this.animationend, this.endBind);
}
// Leave
leave() {
this.ele.classList.add(this.outClass);
this.ele.addEventListener(this.animationend, this.endBind);
}
// Animation end handler
end() {
const ele = this.ele,
eleClassList = ele.classList,
isIn = eleClassList.contains(this.inClass),
isOut = eleClassList.contains(this.outClass);
ele.removeEventListener(this.animationend, this.endBind);
if (isIn) {
eleClassList.remove(this.inClass);
this.inCallback && this.inCallback();
}
if (isOut) {
eleClassList.remove(this.outClass);
this.outCallback && this.outCallback();
}
}
// Detect appropriate animationend event
whichEndEvent() {
const el = document.createElement('div');
const animations = {
"animation": "animationend",
"WebkitAnimation": "webkitAnimationEnd"
};
for (let k in animations) {
if (el.style[k] !== undefined) {
return animations[k];
}
}
}
}Note: This implementation uses CSS animation rather than transition because adding a transition class when the element changes from display:none to display:block does not trigger an animation, whereas animation does.
Usage
function leaveEnd() {
console.log('hello the world');
}
const animateInOut = new AnimateInOut({ele: $el, className: 'fade', outCallback: leaveEnd});
animateInOut.enter(); // trigger enter animation
animateInOut.leave(); // trigger leave animationThe tutorial series is ongoing and more content will be added.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
