This was done for a client, and I do not recommend it as it uses setTimeout()
. Anything using setTimeout()
or setInterval()
slows down the page. Still, as it was a temporary landing page, this is how I approached it.
Demo
See a live demo here.
HTML
The HTML structure is pretty simple and all details are contained into data
parameters. I’d say it’s relatively safe for SEO.
<h2 class="header-text">
roo: <span class="typewrite" data-period="2000" data-type='[ "Is Your Site Slow", "Has Your Site Been Hacked", "Do You Need Website Maintenance", "Do You Want Better Page Speed" ]'>
<span class="wrap"></span>
</span>
</h2>
JavaScript
<script>
let TxtType = function (el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = "";
this.tick();
this.isDeleting = false;
};
TxtType.prototype.tick = function () {
let i = this.loopNum % this.toRotate.length;
let fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = `<span class="wrap">${this.txt}</span>`;
let that = this;
let delta = 100 - Math.random() * 100;
if (this.isDeleting) {
delta /= 4;
}
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === "") {
this.isDeleting = false;
this.loopNum++;
delta = 1000 / 60;
}
setTimeout(() => {
that.tick();
}, delta);
};
document.addEventListener('DOMContentLoaded', () => {
let elements = document.getElementsByClassName('typewrite');
for (let i = 0; i < elements.length; i++) {
let toRotate = elements[i].dataset.type;
let period = elements[i].dataset.period;
if (toRotate) {
new TxtType(elements[i], JSON.parse(toRotate), period);
}
}
});
</script>
CSS
Most of this is for demo purposes only, you only need the animation and the pseudo-element:
.header-text {
font-family: "Poppins";
font-weight: 500;
}
.typewrite > .wrap {
position: relative;
font-weight: 300;
}
.typewrite > .wrap:after {
content: "?";
color: orange;
font-weight: 500;
position: absolute;
animation: blinkerText 1s linear infinite;
}
@keyframes blinkerText {
50% {
opacity: 0;
}
}