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);
}
}
...