Frontend Development 6 min read

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.

<code>@include animation-fade-in;
@include animation-fade-out;</code>

The compiled CSS for the fade animations is:

<code>.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; }
}</code>

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

<code>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];
            }
        }
    }
}
</code>

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

<code>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
</code>

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

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

login 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.