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.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Mastering Enter/Exit Animations with Sandal SCSS Mixins and ES6

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 animation

The tutorial series is ongoing and more content will be added.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptCSSSCSSanimations
Tencent IMWeb Frontend Team
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.