JSFiddle - React, Tailwind, and code Playground

by _nderscore

HTML

<div id="typeme">
    Lorem ipsum dolor amet text node.
</div>

<script>
window.addEventListener('DOMContentLoaded', () => {
    new Typewriter({
        element: typeme
    }).start();
});
</script>

SCSS

body { 
  background: #262c43;
  font-family: "Helvetica", sans-serif;
  font-size: 96px;
  font-weight: bold;
  color: #fff; 
  margin: 5vh 5%;
}

.typewriter {
    /* fix for subpixel antialiasing rendering ~shimmering~
     * text in WebKit during the transition effect */
    -webkit-font-smoothing: antialiased;
    position: relative;

    &__word {
        display: inline-block;
        white-space: pre-wrap;

        &--space:after {
            content: " ";
        }

        &__letter {
            display: inline-block;
            opacity: 0;
            transform: translateY(-1rem);

            &--shown {
                transition: opacity 75ms ease-out,
                            transform 75ms ease-out;
                opacity: 1;
                transform: translateY(0);
            }
        }
    }

    &__cursor {
        position: absolute;
        animation: 1s typewriter-cursor-blink steps(2, start) infinite;

        &:before {
            content: "|";
        }
    }
}

@keyframes "typewriter-cursor-blink" {
    to {
        visibility: hidden;
    }
}

Babel + JSX

/* IE11 POLYFILL */
Array.from = arg => [].slice.call(arg);
/* ------------- */

const TYPEWRITER_CLASS = 'typewriter';
const WORD_CLASS = `${TYPEWRITER_CLASS}__word`;
const LETTER_CLASS = `${WORD_CLASS}__letter`;
const LETTER_SHOWN_CLASS = `${LETTER_CLASS}--shown`;
const SPACE_CLASS = `${WORD_CLASS}--space`;
const CURSOR_CLASS = `${TYPEWRITER_CLASS}__cursor`;

window.Typewriter = class Typewriter {

    constructor({
        element,
        interval = 100,
        delay = 0,
        showCursor = true,
        cursorDelay = 0
    }) {
        this._element = element;
        this._interval = interval;
        this._delay = delay;
        this._cursorDelay = cursorDelay;

        this._letters = [];
        this._timeouts = [];

        const text = element.textContent.trim();
        element.removeChild(element.firstChild);
        element.classList.add(TYPEWRITER_CLASS);

        const words = text.split(/\s+/g);
        const numWords = words.length;

        words.forEach((word, index) => {
            const wordSpan = document.createElement('span');
            wordSpan.classList.add(WORD_CLASS);
            
            if (index !== numWords - 1) {
                wordSpan.classList.add(SPACE_CLASS);
            }

            [...word].forEach((letter) => {
                const letterSpan = document.createElement('span');
                letterSpan.classList.add(LETTER_CLASS);
                letterSpan.appendChild(
                    document.createTextNode(letter)
                );
                wordSpan.appendChild(letterSpan);
                this._letters.push(letterSpan);
            });

            element.appendChild(wordSpan);
        });

        if (showCursor) {
            const cursor = this._cursor = document.createElement('span');
            cursor.classList.add(CURSOR_CLASS);
            cursor.style.top = 0;
            cursor.style.left = 0;
            element.insertBefore(cursor, element.firstChild);
        }
    }

   ...