<div class="emoji-slider">
    <ul>
        <li>awful</li>
        <li>bad</li>
        <li>okay</li>
        <li>good</li>
        <li>great</li>
    </ul>
    <div class="smiley">
        <svg class="eye left" viewBox="0 0 18 22">
            <path d="M12.6744144,18.0128897 C17.3794842,15.6567898 19.3333811,9.83072065 17.0385652,5 C15.7595661,7.57089081 13.5517099,9.64170285 10.4149967,11.2124361 C7.27828344,12.7831694 3.80661788,13.5564215 0,13.5321925 C2.2948159,18.3629131 7.9693445,20.3689896 12.6744144,18.0128897 Z"></path>
        </svg>
        <svg class="eye right" viewBox="0 0 18 22">
            <path d="M12.6744144,18.0128897 C17.3794842,15.6567898 19.3333811,9.83072065 17.0385652,5 C15.7595661,7.57089081 13.5517099,9.64170285 10.4149967,11.2124361 C7.27828344,12.7831694 3.80661788,13.5564215 0,13.5321925 C2.2948159,18.3629131 7.9693445,20.3689896 12.6744144,18.0128897 Z"></path>
        </svg>
        <svg class="mouth" viewBox="0 0 64 28">
            <path d="M32,2 C41.5729357,2 58,10.8218206 58,21 C50.2396023,18.9643641 41.5729357,17.9465462 32,17.9465462 C22.4270643,17.9465462 13.7603977,18.9643641 6,21 C6,10.8218206 22.4270643,2 32,2 Z"></path>
        </svg>
        <svg class="teeth" viewBox="0 0 64 28">
            <path d="M32,7.83261436 C41.5729357,7.83261436 52.5729357,7.05507624 63,1.5 C63,10.3056732 46.3594035,14.5 32,14.5 C17.6405965,14.5 1,10.3056732 1,1.5 C11.4270643,7.05507624 22.4270643,7.83261436 32,7.83261436 Z"></path>
        </svg>
    </div>
    <div class="slide">
        <div></div>
    </div>
    <div class="bottom">
        I'm feeling
        <ul>
            <li>awful</li>
            <li>bad</li>
            <li>okay</li>
            <li>good</li>
            <li>great</li>
        </ul>
        <button>Save</button>
    </div>
</div>

<svg style="position: absolute; visibility: hidden;">
    <defs>
        <filter id="inset-shadow">
            <feOffset dx='0' dy='3' />
            <feGaussianBlur stdDeviation='1' result='offset-blur' />
            <feComposite operator='out' in='SourceGraphic' in2='offset-blur' result='inverse' />
            <feFlood flood-color='black' flood-opacity='.5' result='color' />
            <feComposite operator='in' in='color' in2='inverse' result='shadow' />
            <feComposite operator='over' in='shadow' in2='SourceGraphic' />
        </filter>
    </defs>
</svg>

<!-- dribbble - twitter -->
<a class="dribbble" href="https://dribbble.com/shots/8583409-Morphing-Emoji-Slider" target="_blank"><img src="https://cdn.dribbble.com/assets/dribbble-ball-mark-2bd45f09c2fb58dbbfb44766d5d1d07c5a12972d602ef8b32204d28fa3dda554.svg" alt=""></a>
<a class="twitter" target="_blank" href="https://twitter.com/aaroniker_me"><svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" viewBox="0 0 72 72"><path d="M67.812 16.141a26.246 26.246 0 0 1-7.519 2.06 13.134 13.134 0 0 0 5.756-7.244 26.127 26.127 0 0 1-8.313 3.176A13.075 13.075 0 0 0 48.182 10c-7.229 0-13.092 5.861-13.092 13.093 0 1.026.118 2.021.338 2.981-10.885-.548-20.528-5.757-26.987-13.679a13.048 13.048 0 0 0-1.771 6.581c0 4.542 2.312 8.551 5.824 10.898a13.048 13.048 0 0 1-5.93-1.638c-.002.055-.002.11-.002.162 0 6.345 4.513 11.638 10.504 12.84a13.177 13.177 0 0 1-3.449.457c-.846 0-1.667-.078-2.465-.231 1.667 5.2 6.499 8.986 12.23 9.09a26.276 26.276 0 0 1-16.26 5.606A26.21 26.21 0 0 1 4 55.976a37.036 37.036 0 0 0 20.067 5.882c24.083 0 37.251-19.949 37.251-37.249 0-.566-.014-1.134-.039-1.694a26.597 26.597 0 0 0 6.533-6.774z"></path></svg></a>
.emoji-slider {
    // Awful colors
    --awful-gradient-start: #FD8D58;
    --awful-gradient-end: #DC611E;
    --awful-fill: #FB8043;
    --awful-radial: #FFCCB0;
    --awful-border: #{rgba(#DE5B1A, .5)};
    --awful-shadow: #{rgba(#90420E, .5)};
    --awful-mouth-fill: #A34106;
    --awful-mouth-shadow: #{rgba(#C45F28, .6)};
    --awful-mouth-shine: #FEC6A7;
    --awful-color: #ffaa68;
    // Bad colors
    --bad-gradient-start: #FEA954;
    --bad-gradient-end: #DA7315;
    --bad-fill: #FCA730;
    --bad-radial: #FEE8C6;
    --bad-border: #{rgba(#E07B13, .5)};
    --bad-shadow: #{rgba(#BC600C, .5)};
    --bad-mouth-fill: #AB6C09;
    --bad-mouth-shadow: #{rgba(#945907, .4)};
    --bad-mouth-shine: #FDE0B4;
    --bad-color: #fbba4a;
    // Okay colors
    --okay-gradient-start: #FEBE53;
    --okay-gradient-end: #DF820F;
    --okay-fill: #FBBB1F;
    --okay-radial: #FEF3BD;
    --okay-border: #{rgba(#E08F06, .5)};
    --okay-shadow: #{rgba(#BE6D09, .5)};
    --okay-mouth-fill: #AB7509;
    --okay-mouth-shadow: #{rgba(#926807, .4)};
    --okay-mouth-shine: #FFEECE;
    --okay-color: #fbd24b;
    // Good colors
    --good-gradient-start: #FED151;
    --good-gradient-end: #DE981F;
    --good-fill: #FBD51F;
    --good-radial: #FEF3BD;
    --good-border: #{rgba(#D5A50E, .5)};
    --good-shadow: #{rgba(#BB840F, .5)};
    --good-mouth-fill: #AB7509;
    --good-mouth-shadow: #{rgba(#926807, .4)};
    --good-mouth-shine: #FFEECE;
    --good-color: #fcd34a;
    // Great colors
    --great-gradient-start: #A1BD53;
    --great-gradient-end: #73AD5F;
    --great-fill: #F4EF51;
    --great-radial: #FDFDEC;
    --great-border: #{rgba(#A7BB2E, .5)};
    --great-shadow: #{rgba(#888632, .5)};
    --great-mouth-fill: #8A8313;
    --great-mouth-shadow: #{rgba(#5D5003, .25)};
    --great-mouth-shine: #FDF8B4;
    --great-color: #d2f482;
    width: 320px;
    height: 288px;
    border-radius: 13px;
    overflow: hidden;
    position: relative;
    background-image: linear-gradient(var(--gradient-start, var(--awful-gradient-start)),  var(--gradient-end, var(--awful-gradient-end)));
    ul {
        margin: 0;
        padding: 0;
        list-style: none;
    }
    & > ul,
    .bottom ul {
        li {
            transform: translateY(var(--y, 0));
            opacity: var(--o, 0);
            transition: opacity .2s;
            &:not(:first-child) {
                width: 100%;
                position: absolute;
            }
            @for $i from 2 through 5 {
                &:nth-child(#{$i}) {
                    top: 100% * ($i - 1);
                }
            }
        }
    }
    &.awful {
        & > ul,
        .bottom ul {
            li:nth-child(1) {
                --o: 1;
            }
        }
    }
    &.bad {
        & > ul,
        .bottom ul {
            li:nth-child(2) {
                --o: 1;
            }
        }
    }
    &.okay {
        & > ul,
        .bottom ul {
            li:nth-child(3) {
                --o: 1;
            }
        }
    }
    &.good {
        & > ul,
        .bottom ul {
            li:nth-child(4) {
                --o: 1;
            }
        }
    }
    &.great {
        & > ul,
        .bottom ul {
            li:nth-child(5) {
                --o: 1;
            }
        }
        .smiley {
            svg {
                &.teeth {
                    --teeth: 1;
                }
            }
        }
    }
    &.scale {
        .smiley {
            animation: scale .6s ease forwards;
        }
    }
    & > ul {
        top: 12px;
        left: 0;
        right: 0;
        font-size: 80px;
        font-weight: 900;
        opacity: .4;
        text-align: center;
        position: absolute;
        text-transform: uppercase;
        li {
            user-select: none;
            background-image: linear-gradient(rgba(#fff, .9), rgba(#fff, 0) 90%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
    }
    .smiley {
        width: 120px;
        height: 120px;
        border-radius: 50%;
        z-index: 1;
        margin: 60px auto 0 auto;
        position: relative;
        background: radial-gradient(circle, var(--radial, var(--awful-radial)) 0%, var(--fill, var(--awful-fill)) 70%);
        background-size: 100% 180%;
        background-position: center bottom;
        box-shadow: inset 0 0 0 4px var(--border, var(--awful-border)), inset 0 -10px 12px var(--shadow, var(--awful-shadow));
        filter: drop-shadow(0 8px 16px rgba(#000, .16));
        svg {
            display: block;
            position: absolute;
            backface-visibility: hidden;
            transform: translateZ(0);
            fill: var(--mouth-fill, var(--awful-mouth-fill));
            &.eye {
                width: 18px;
                height: 22px;
                top: 34px;
                filter: drop-shadow(0 1px 2px var(--mouth-shine, var(--awful-mouth-shine))) url(#inset-shadow);
                &.left {
                    left: 30px;
                }
                &.right {
                    right: 30px;
                    transform: scaleX(-1);
                }
            }
            &.mouth,
            &.teeth {
                width: 64px;
                height: 28px;
                left: 28px;
                bottom: 24px;
            }
            &.mouth {
                filter: drop-shadow(0 1px 2px var(--mouth-shine, var(--awful-mouth-shine))) drop-shadow(0 -1px 1px var(--mouth-shadow, var(--awful-mouth-shadow))) url(#inset-shadow);
            }
            &.teeth {
                fill: #fff;
                opacity: var(--teeth, 0);
                transition: opacity .2s;
            }
        }
    }
    .slide {
        left: 28px;
        right: 28px;
        bottom: 68px;
        height: 12px;
        position: absolute;
        div {
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: #fff;
            top: -6px;
            left: -12px;
            box-shadow: 0 2px 6px rgba(#000, .2);
            position: relative;
        }
        &:before {
            content: '';
            position: absolute;
            top: 0;
            left: -3px;
            width: 273px;
            height: 12px;
            background-image: url('data:image/svg+xml;utf8,<svg width="273px" height="12px" viewBox="0 0 273 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M266.934082,0.00110627889 C270.247182,-0.0357036686 272.96282,2.62025389 272.99963,5.93335351 C272.999877,5.95556942 273,5.97778653 273,6.00000382 C273,9.31330792 270.314036,11.9992716 267.000732,11.9992716 C266.978515,11.9992716 266.956298,11.9991482 266.934082,11.9989014 L2.96667078,9.06611103 C1.32291919,9.04784825 1.97412392e-14,7.71014921 0,6.06629617 L0,5.93371146 C9.7279267e-16,4.28985843 1.32291919,2.95215939 2.96667078,2.93389661 L266.934082,0.00110627889 Z M267,1.45028446 C264.514719,1.45028446 262.5,3.4872632 262.5,6.00000382 C262.5,8.51274443 264.514719,10.5497232 267,10.5497232 C269.485281,10.5497232 271.5,8.51274443 271.5,6.00000382 C271.5,3.4872632 269.485281,1.45028446 267,1.45028446 Z M210,1.95580884 C207.790861,1.95580884 206,3.7664566 206,6.00000382 C206,8.23355103 207.790861,10.0441988 210,10.0441988 C212.209139,10.0441988 214,8.23355103 214,6.00000382 C214,3.7664566 212.209139,1.95580884 210,1.95580884 Z M137,2.46133321 C135.067003,2.46133321 133.5,4.04565001 133.5,6.00000382 C133.5,7.95435763 135.067003,9.53867443 137,9.53867443 C138.932997,9.53867443 140.5,7.95435763 140.5,6.00000382 C140.5,4.04565001 138.932997,2.46133321 137,2.46133321 Z M64,2.96685758 C62.3431458,2.96685758 61,4.32484341 61,6.00000382 C61,7.67516423 62.3431458,9.03315005 64,9.03315005 C65.6568542,9.03315005 67,7.67516423 67,6.00000382 C67,4.32484341 65.6568542,2.96685758 64,2.96685758 Z M3,3.97790633 C1.8954305,3.97790633 1,4.88323021 1,6.00000382 C1,7.11677742 1.8954305,8.02210131 3,8.02210131 C4.1045695,8.02210131 5,7.11677742 5,6.00000382 C5,4.88323021 4.1045695,3.97790633 3,3.97790633 Z" fill="white" fill-opacity=".25"></path></svg>');
        }
    }
    .bottom {
        left: 0;
        right: 0;
        bottom: 0;
        font-size: 14px;
        line-height: 23px;
        color: rgba(#fff, .8);
        padding: 8px 16px;
        border-radius: 0 0 13px 13px;
        background: rgba(#000, .1);
        position: absolute;
        ul {
            font-weight: 900;
            vertical-align: top;
            position: relative;
            display: inline-block;
            color: var(--color, var(--awful-color));
        }
        button {
            -webkit-appearance: none;
            border: 0;
            margin: 0;
            padding: 0 12px;
            line-height: 25px;
            height: 25px;
            border-radius: 13px;
            position: absolute;
            cursor: pointer;
            outline: none;
            color: #fff;
            text-transform: uppercase;
            font-weight: bold;
            font-size: 12px;
            right: 16px;
            top: 7px;
            background: var(--gradient-end, var(--awful-gradient-end));
        }
    }
}

@keyframes scale {
    50% {
        transform: scale(1.08) translateZ(0);
        filter: drop-shadow(0 8px 24px rgba(#000, .12));
    }
}

html {
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
}

* {
    box-sizing: inherit;
    &:before,
    &:after {
        box-sizing: inherit;
    }
}

// Center & dribbble
body {
    min-height: 100vh;
    display: flex;
    font-family: 'Inter UI', Arial;
    justify-content: center;
    align-items: center;
    background: #F6F8FF;
    .dribbble {
        position: fixed;
        display: block;
        right: 20px;
        bottom: 20px;
        img {
            display: block;
            height: 28px;
        }
    }
    .twitter {
        position: fixed;
        display: block;
        right: 64px;
        bottom: 14px;
        svg {
            width: 32px;
            height: 32px;
            fill: #1da1f2;
        }
    }
}
View Compiled
const $ = (s, o = document) => o.querySelector(s);
const $$ = (s, o = document) => o.querySelectorAll(s);

let emoji = $('.emoji-slider'),
    button = $('button', emoji),
    slider = $('.slide', emoji),
    drag = $('div', slider),
    smiley = $('.smiley', emoji),
    points = {
        0: {
            name: 'awful',
            mouth: 'M32,2 C41.5729357,2 58,10.8218206 58,21 C50.2396023,18.9643641 41.5729357,17.9465462 32,17.9465462 C22.4270643,17.9465462 13.7603977,18.9643641 6,21 C6,10.8218206 22.4270643,2 32,2 Z',
            eye: 'M12.6744144,18.0128897 C17.3794842,15.6567898 19.3333811,9.83072065 17.0385652,5 C15.7595661,7.57089081 13.5517099,9.64170285 10.4149967,11.2124361 C7.27828344,12.7831694 3.80661788,13.5564215 0,13.5321925 C2.2948159,18.3629131 7.9693445,20.3689896 12.6744144,18.0128897 Z'
        },
        61: {
            name: 'bad',
            mouth: 'M32,6 C41.5729357,6 62,10.80044 62,23 C52.2396023,17.5602347 42.2396023,14.840352 32,14.840352 C21.7603977,14.840352 11.7603977,17.5602347 2,23 C2,10.80044 22.4270643,6 32,6 Z',
            eye: 'M9,19 C14.418278,19 17,15.418278 17,11 C17,6.581722 14.418278,3 9,3 C3.581722,3 1,6.581722 1,11 C1,15.418278 3.581722,19 9,19 Z'
        },
        134: {
            name: 'okay',
            mouth: 'M32,11.3326144 C41.5729357,11.3326144 51.5729357,9.55507624 62,4 C62,12.8056732 46.3594035,23 32,23 C17.6405965,23 2,12.8056732 2,4 C12.4270643,9.55507624 22.4270643,11.3326144 32,11.3326144 Z',
            eye: 'M9,19 C14.418278,19 17,15.418278 17,11 C17,6.581722 14.418278,3 9,3 C3.581722,3 1,6.581722 1,11 C1,15.418278 3.581722,19 9,19 Z'
        },
        207: {
            name: 'good',
            mouth: 'M32,6.33261436 C41.5729357,6.33261436 51.5729357,5.55507624 62,0 C62,8.80567319 46.3594035,25 32,25 C17.6405965,25 2,8.80567319 2,0 C12.4270643,5.55507624 22.4270643,6.33261436 32,6.33261436 Z',
            eye: 'M9,21 C13.418278,21 17,16.418278 17,11 C17,5.581722 13.418278,1 9,1 C4.581722,1 1,5.581722 1,11 C1,16.418278 4.581722,21 9,21 Z'
        },
        264: {
            name: 'great',
            mouth: 'M32,6.33261436 C41.5729357,6.33261436 53.5729357,5.55507624 64,0 C64,8.80567319 51.3594035,27 32,27 C12.6405965,27 0,8.80567319 0,0 C10.4270643,5.55507624 22.4270643,6.33261436 32,6.33261436 Z',
            eye: 'M9,22 C13.418278,22 17,16.418278 17,11 C17,5.581722 13.418278,0 9,0 C4.581722,0 1,5.581722 1,11 C1,16.418278 4.581722,22 9,22 Z'
        }
    };

gsap.registerPlugin(MorphSVGPlugin);
gsap.registerPlugin(InertiaPlugin);

function setEmoji(value, duration = .4) {
    let index = value == 0 ? value : Object.keys(points).indexOf(value),
        name = points[value].name,
        computed = getComputedStyle(emoji);
    emoji.classList.remove('awful', 'bad', 'okay', 'good', 'great');
    emoji.classList.add(name, 'scale');
    gsap.to(emoji, {
        '--y': index * -100 + '%',
        '--gradient-start': computed.getPropertyValue('--' + name + '-gradient-start'),
        '--gradient-end': computed.getPropertyValue('--' + name + '-gradient-end'),
        '--fill': computed.getPropertyValue('--' + name + '-fill'),
        '--radial': computed.getPropertyValue('--' + name + '-radial'),
        '--border': computed.getPropertyValue('--' + name + '-border'),
        '--shadow': computed.getPropertyValue('--' + name + '-shadow'),
        '--mouth-fill': computed.getPropertyValue('--' + name + '-mouth-fill'),
        '--mouth-shadow': computed.getPropertyValue('--' + name + '-mouth-shadow'),
        '--mouth-shine': computed.getPropertyValue('--' + name + '-mouth-shine'),
        '--color': computed.getPropertyValue('--' + name + '-color'),
        duration: duration
    });
    gsap.to($$('.eye path', smiley), {
        morphSVG: points[value].eye,
        duration: .4
    });
    gsap.to($('.mouth path', smiley), {
        morphSVG: points[value].mouth,
        duration: .4
    });
    setTimeout(() => emoji.classList.remove('scale'), 600);
    return value;
}

Draggable.create(drag, {
    type: 'x',
    bounds: {
        left: -drag.offsetWidth / 2,
        width: slider.offsetWidth + drag.offsetWidth
    },
    inertia: true,
    snap(value) {
        return setEmoji(Object.keys(points).reduce((p, c) => {
            return (Math.abs(c - value) < Math.abs(p - value) ? c : p);
        }));
    }
});

button.addEventListener('click', e => {
    let x = Draggable.get(drag).x,
        value = Object.keys(points).reduce((p, c) => {
            return (Math.abs(c - x) < Math.abs(p - x) ? c : p);
        });
    alert('Selected: ' + points[value].name);
});

setEmoji(0, 0);

External CSS

  1. https://cdn.jsdelivr.net/npm/inter-ui@3.11.0/inter.min.css

External JavaScript

  1. https://cdn.jsdelivr.net/npm/gsap@3.0.1/dist/gsap.min.js
  2. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/Draggable3.min.js
  3. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/MorphSVGPlugin3.min.js
  4. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/InertiaPlugin.min.js