JSFiddle - React, Tailwind, and code Playground
by mihaibirsan
HTML
<div class="description">
<p class="typewriter">
Hello <strong>Merwllyra</strong>!<br>
You were waiting for the taxi boat in the port and fell asleep.
</p>
</div>
CSS
html, body { background: #1F2227; }
.description {
width: 15em;
background: #FFFAE4;
color: #827256;
padding: 1em;
border-radius: .5em;
}
.description p {
margin: 0;
}
/* NOTE: Many of these values are computed manually and would better be extracted into SCSS. However, I wasn't able to get SCSS to work, so this version of the fiddle just has the numbers. */
.typewriter {
line-height: 1.2em;
}
.typewriter > div {
height: 1.2em;
overflow: hidden;
animation: reveal 1s steps(17, jump-none) both; /* NOTE: Prefer `linear` instead of `steps` with variable-width fonts. */
}
.typewriter > div > div {
width: 15em; /* NOTE: This width must be fixed here. So the reveal can work. */
}
.typewriter > div:nth-child(2) {
width: 0;
animation-delay: 1s;
}
.typewriter > div:nth-child(3) {
animation-delay: 2s;
}
.typewriter > div:nth-child(2) > div {
margin-top: -1.2em;
}
.typewriter > div:nth-child(3) > div {
margin-top: -2.4em;
}
@keyframes reveal {
from { width: 0; }
to { width: 100%; }
}
JavaScript
// NOTE: This duplication is unnecessarily complex in plain JS; consider implementing using your favorite library
const el = document.querySelector('p.typewriter');
const elInnerHTML = el.innerHTML;
el.innerHTML = '';
for (let i = 0; i < 3; i++) {
const divEl = document.createElement('div');
divEl.classList.add('typewriter-'+(i+1))
const innerDivEl = document.createElement('div');
innerDivEl.innerHTML = elInnerHTML;
divEl.appendChild(innerDivEl);
el.appendChild(divEl);
}