I have some misbehaving text in a CSS animation.
The text appears to "type" itself out, and then end with a blinking cursor. It does this well, but when it's done typing a line that line tends to "float" or "shift" itself over to the center of the page.
I am centering the text with text-align: center; as well as with a flexbox (to get it center of the page).
Here's a link to a JSFiddle
And here's some code:
html, body {
height: 100%;
width: 100%;
}
body {
overflow-x: hidden;
overflow-y: hidden;
}
.do-you-even-flexbox, .content {
position:relative;
top:0;
width:100%;
height:100%;
}
.content {
padding:8px 20px 15px;
display:flex;
align-content:center;
}
.box {
height:20%;
margin:auto
}
h1 {
text-align: center;
font-size: 75px;
margin-top: 0em;
margin-bottom: 0em;
padding: 0em;
}
h2 {
font-size: 50px;
text-align: center;
margin-top: 0em;
margin-bottom: 0em;
padding: 0em;
}
h3 {
font-size: 25px;
text-align: center;
margin-top: 0em;
margin-bottom: 0em;
padding: 0em;
}
a {
color: #000;
text-decoration: none;
}
.content h1 {
white-space:nowrap;
overflow:hidden;
-webkit-animation: typing 5s steps(60, end);
-moz-animation: typing 5s steps(60, end);
}
.content h2 {
white-space:nowrap;
overflow:hidden;
-webkit-animation: typing 5s steps(60, end);
-webkit-animation-delay: 4s;
-webkit-animation-fill-mode:both;
-moz-animation: typing 5s steps(60, end);
-moz-animation-delay:4s;
-moz-animation-fill-mode:both;
}
.content h3 {
white-space: nowrap;
overflow: hidden;
-webkit-animation: typing 10s steps(120, end);
-webkit-animation-delay: 8s;
-webkit-animation-fill-mode: both;
-moz-animation: typing 10s steps(120, end);
-moz-animation-delay: 8s;
-moz-animation-fill-mode: both;
}
span {
-webkit-animation: blink 1s infinite;
-moz-animation: blink 1s infinite;
}
#-webkit-keyframes typing {
from { width: 0; }
to { width: 100%; }
}
#-webkit-keyframes blink {
to { opacity: .0;}
}
#-moz-keyframes typing {
from { width: 0; }
to { width: 100%; }
}
#-moz-keyframes blink {
to { opacity: .0; }
}
And here's some HTML that goes with it:
<i class="do-you-even-flexbox"></i>
<div class="content">
<div class="box">
<h1>This wasn't the same as the fiddle code.</p>
<h2>So I've removed some details so it's similar to the fiddle.</p>
<h3>~ get in touch ~ about me ~ blog ~ projects ~ my portfolio ~<span> |</span></h3>
</div>
</div>
well, the problem seems to be with the animation from 0 to 100%, since Heading tags are blocks, and blocks always are 100% percent from its container, the animation actually goes from 0 to the total width of the page. What you are trying to do here its a little bit tricky but can be done nesting a tag inside every Heading tag and animating that tag while giving each heading tag inline behavior which ensures the width is not 100% of the container but just the text.
html, body {
height: 100%;
width: 100%;
}
body {
overflow-x: hidden;
overflow-y: hidden;
}
.do-you-even-flexbox, .content {
position:relative;
top:0;
width:100%;
height:100%;
}
.content {
padding:8px 20px 15px;
display:flex;
align-content:center;
}
.box {
height:20%;
margin:auto
text-align: center;
}
h1, h2, h3 {
display: inline-block;
position: relative;
background-color: #cccccc;
}
h1 span {
font-size: 75px;
margin: 0;
padding: 0em;
display: block;
background-color: #ff0000;
}
h2 span {
font-size: 50px;
text-align: center;
margin-top: 0em;
margin-bottom: 0em;
padding: 0em;
}
h3 span {
font-size: 25px;
text-align: center;
margin-top: 0em;
margin-bottom: 0em;
padding: 0em;
}
a {
color: #000;
text-decoration: none;
}
.content h1 span {
white-space:nowrap;
overflow:hidden;
-webkit-animation: typing 2s steps(60, end);
-moz-animation: typing 2s steps(60, end);
}
.content h2 {
white-space:nowrap;
overflow:hidden;
-webkit-animation: typing 2s steps(60, end);
-webkit-animation-delay: 2s;
-webkit-animation-fill-mode:both;
-moz-animation: typing 2s steps(60, end);
-moz-animation-delay:2s;
-moz-animation-fill-mode:both;
}
.content h3 {
white-space: nowrap;
overflow: hidden;
-webkit-animation: typing 10s steps(120, end);
-webkit-animation-delay: 2s;
-webkit-animation-fill-mode: both;
-moz-animation: typing 2s steps(120, end);
-moz-animation-delay: 2s;
-moz-animation-fill-mode: both;
}
span.caret {
-webkit-animation: blink 1s infinite;
-moz-animation: blink 1s infinite;
}
#-webkit-keyframes typing {
from { width: 0; }
to { width: 100%; }
}
#-webkit-keyframes blink {
to { opacity: .0;}
}
#-moz-keyframes typing {
from { width: 0; }
to { width: 100%; }
}
#-moz-keyframes blink {
to { opacity: .0; }
}
<i class="do-you-even-flexbox"></i>
<div class="content">
<div class="box">
<h1><span>This</span></h1>
<br>
<h2><span>This is a subtitile</span></h2>
<br>
<h3><span>These are links to things on other pages.<span class="caret">|</span> </span></h3>
</div>
</div>
Related
So with the possibilities of HTML marquee, I came super close to what I want to create.
.marquee {
background-color: antiquewhite;
width: 150px;
margin: 0 auto;
overflow: hidden;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.marquee span {
font-size: 40px;
position: relative;
left: 100%;
animation: marquee 2s linear infinite;
}
.marquee:hover span {
animation-play-state: paused;
}
.marquee span:nth-child(1) {
animation-delay: 0s;
}
.marquee span:nth-child(2) {
animation-delay: 0.8s;
}
.marquee span:nth-child(3) {
animation-delay: 1.6s;
}
.marquee span:nth-child(4) {
animation-delay: 2.4s;
}
.marquee span:nth-child(5) {
animation-delay: 3.2s;
}
#keyframes marquee {
0% {left: 100%;}
100% {left: -100%;}
}
p{
display: inline;
}
<p class="marquee">
<span>this is a</span>
<span>simple marquee</span>
<span>using css</span>
<span>using css</span>
<span>simple marquee</span>
</p>
The only 2 problems:
I don't know how to change the height so that the text will stay in the middle
The words overlap and I can't create a clean loop of the words
UPDATE:
I assume I made it. If anything inside this code is a no-go, please let me know.
If not, this will be a possible CSS only solution for anybody who wants to achieve something similar:
HTML:
<div class="marqueemagic">
<div class="scrollingquee">
</div><div class="scrollingquee" aria-hidden="true">
<i> CONVERSION | OPTIMIZATION |</i>
</div><div class="scrollingquee" aria-hidden="true">
<i>CONVERSION | OPTIMIZATION |</i>
</div><div class="scrollingquee" aria-hidden="true">
<i> CONVERSION | OPTIMIZATION |</i>
</div>
<!-- … -->
</div>
CSS:
.marqueemagic {
overflow: hidden;
white-space: nowrap;
width: 150px;
background-color: white;
display: inline-block;
padding-bottom: 5px;
padding-top: 5px;
margin-bottom: 2px;
font-size: 35px;
vertical-align: bottom;
font-weight: 600;
}
.scrollingquee {
animation: marquee 5s linear infinite;
display: inline-block;
padding-right: 10px;
}
#keyframes marquee {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
Result:
https://youtu.be/Tuy4FUZmVd8
Of course, you can change speed, width, background color, opacity, font related values etc. as you wish without breaking anything.
With kind regards
Chris
I want to create a writing animation which is infinite and alternate. Everything works fine but for some reason the last letter does always get cut off.
I hope somebody can explain why it gets cut off and how to fix this.
My code:
body {
height: 100vh;
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
}
li {
list-style-type: none;
}
.first {
font-size: 2.5rem;
position: relative;
width: max-content;
}
.first::before,
.first::after {
content: '';
position: absolute;
height: 3.5rem;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.first::before {
background-color: white;
animation: typewriter 1.5s steps(7) alternate infinite;
}
.first::after {
width: .125rem;
background-color: black;
animation: typewriter 1.5s steps(7) alternate infinite, blink 500ms steps(7) infinite;
}
#keyframes typewriter {
to {
left: 100%;
}
}
#keyframes blink {
to {
background: transparent;
}
}
<li class="first">student</li>
Here is a generic method from my article: https://dev.to/afif/a-scalable-css-only-typewriter-effect-2opn
body {
height: 100vh;
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
}
li {
list-style-type: none;
}
.first {
font-size: 2.5rem;
}
.type {
font-size:50px;
display:inline-flex;
}
.type span {
height:1.2em;
width:0%;
word-break:break-all;
overflow: hidden;
animation:
c 0.2s infinite steps(1),
t 3s linear infinite alternate;
}
.type span:before {
content:" ";
display:inline-block;
}
#keyframes t{
90%,100% {width:100%}
}
#keyframes c{
0%,100%{box-shadow:2px 0 0 #0000}
50% {box-shadow:2px 0 0 #000 }
}
<li class="first type"><span>student</span></li>
Using your method, update the code like below. You have to consider 8 steps and add 1ch to the final left value
body {
height: 100vh;
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
}
li {
list-style-type: none;
}
.first {
font-size: 2.5rem;
position: relative;
width: max-content;
}
.first::before,
.first::after {
content: '';
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
}
.first::before {
background-color: white;
animation: typewriter 1.5s steps(8) alternate infinite;
}
.first::after {
width: .125rem;
background-color: black;
animation:
typewriter 1.5s steps(8) alternate infinite,
blink 500ms steps(8) infinite;
}
#keyframes typewriter {
to {
left: calc(100% + 1ch);
}
}
#keyframes blink {
to {
background: transparent;
}
}
<li class="first">student</li>
Increase your left value and increase your step count.
body {
height: 100vh;
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
}
li {
list-style-type: none;
}
.first {
font-size: 2.5rem;
position: relative;
width: max-content;
}
.first::before,
.first::after {
content: '';
position: absolute;
height: 3.5rem;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.first::before {
background-color: white;
animation: typewriter 1.5s steps(8) alternate infinite;
}
.first::after {
width: .125rem;
background-color: black;
animation: typewriter 1.5s steps(8) alternate infinite, blink 500ms steps(8) infinite;
}
#keyframes typewriter {
to {
left: 110%;
}
}
#keyframes blink {
to {
background: transparent;
}
}
<li class="first">student</li>
Longer words:
body {
height: 100vh;
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
}
li {
list-style-type: none;
margin: 3em 0;
}
.first {
font-size: 2.5rem;
position: relative;
width: max-content;
}
.first::before,
.first::after {
content: '';
position: absolute;
height: 3.5rem;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.first::before {
background-color: white;
animation: typewriter 1.5s steps(8) alternate infinite;
}
.first::after {
width: .125rem;
background-color: black;
animation: typewriter 1.5s steps(8) alternate infinite, blink 500ms steps(8) infinite;
}
.second::before {
background-color: white;
animation: typewriter 2.5s steps(16) alternate infinite;
}
.second::after {
width: .125rem;
background-color: black;
animation: typewriter 2.5s steps(16) alternate infinite, blink 500ms steps(16) infinite;
}
#keyframes typewriter {
to {
left: 110%;
}
}
#keyframes blink {
to {
background: transparent;
}
}
<ul>
<li class="first">student</li>
<li class="first second">studentstudent</li>
</ul>
I am trying to get my text that has a typing effect to center in the middle of this div but I can't get it to work. Here below you can see my code that I tried using but it would fit the job. It will still display the text at the left of the div.
<header class="masthead text-white text-center">
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class="col-xl-10 css-typing mx-auto ">
<p>
Hey! Ik ben
</p>
<p>
Tom Faas
</p>
</div>
</div>
</div>
</header>
The CSS code:
.css-typing p {
border-right: .15em solid white;
font-family: "Courier";
font-size: 14px;
white-space: nowrap;
overflow: hidden;
}
.css-typing p:nth-child(1) {
width: 7.3em;
text-align: center;
-webkit-animation: type 2s steps(40, end);
animation: type 2s steps(40, end),
blinkTextCursor 500ms steps(44) infinite normal;;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
.css-typing p:nth-child(2) {
width: 7.3em;
font-size: 200%;
text-align: center;
opacity: 0;
-webkit-animation: type2 2s steps(40, end);
animation: type2 2s steps(40, end),
blinkTextCursor 500ms steps(44) infinite normal;;
-webkit-animation-delay: 2s;
animation-delay: 2s;
animation-fill-mode: forwards;
}
#keyframes type {
0% {
width: 0;
}
99.9% {
border-right: .15em solid white;
}
100% {
opacity: 1;
border: none;
}
}
#-webkit-keyframes type {
0% {
width: 0;
}
99.9% {
border-right: .15em solid white;
}
100% {
opacity: 1;
border: none;
}
}
#keyframes type2 {
0% {
width: 0;
}
1% {
opacity: 1;
}
99.9% {
border-right: .15em solid white;
}
100% {
opacity: 1;
border: none;
}
}
#-webkit-keyframes type2 {
0% {
width: 0;
}
1% {
opacity: 1;
}
99.9% {
border-right: .15em solid white;
}
100% {
opacity: 1;
border: none;
}
}
As you can see in the example I tried using the mx-auto tagg but It won't center the text and will still put it at the left of the div.
add below CSS property where you use mx-auto. It will center your text.
display: flex;
flex-direction: column;
align-items: center;
I have an h2 header text with the class name "headertekst". I want to center it. I tried to use margin-left: auto, margin-right: auto and width: 100% but nothing happened.
I can give it a margin-left: 20% which will center it but that's just on my laptop. It will not be centered on other screen sizes and on mobile devices.
How do I center it the correct way?
You can just add style in h2 as:
<h2 style="text-align: center;">Text</h2>
h2.headertekst {
text-align: center;
}
<h2 class="headertekst">Test 1</h2>
You can use below css for this
h2 {
width: 100%;
text-align:center;
}
Or
header {
text-align: center;
}
h2 {
display: inline-block;
}
<h2 class="headertekst"> centered text </h2>
.headertekst {
{
text-align: center;
width:100%
}
This is all you need:
.headertekst {
text-align: center;
}
And if you need to center the h2 itself, then just add the text-align: center rule to the parent of the h2 tag.
add style as:
.headertekst{
text-align: center;
}
Here is a workign snippet:
.headertekst{
text-align: center;
}
<h2 class="headertekst">Align this to center</h2>
Ok, the problem is that the last part of your heading is rotating and position absolute. You have to define an approximate average width of the three rotating words.
body {
background: #363636;
}
.headertekst {
color: white;
font-size: 20px;
font-family: "Raleway", Helvetica, Arial, sans-serif;
font-weight: 600;
text-transform: uppercase;
text-align: center;
}
.headertekstrotate {
position: relative;
display: inline-block;
padding: 0 0 0 8px;
width: 150px;
}
.headertekstrotate span {
animation: clock 12s linear infinite 0s;
-ms-animation: clock 12s linear infinite 0s;
-webkit-animation: clock 12s linear infinite 0s;
position: absolute;
left: 0;
top: 0;
opacity: 0;
}
.headertekstrotate span:nth-child(2) {
animation-delay: 4s;
-ms-animation-delay: 4s;
-webkit-animation-delay: 4s;
}
.headertekstrotate span:nth-child(3) {
animation-delay: 8s;
-ms-animation-delay: 8s;
-webkit-animation-delay: 8s;
}
#keyframes clock {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
25% {
opacity: 1;
}
30% {
opacity: 0;
}
80% {
opacity: 0;
}
100% {
opacity: 0;
}
}
<h2 class="headertekst">Interlaser is
<div class="headertekstrotate">
<span>professioneel.</span>
<span>voordelig.</span>
<span>betrouwbaar.</span>
</div>
</h2>
Other way:
body {
background: #363636;
}
.headertekst {
color: white;
font-size: 20px;
font-family: "Raleway", Helvetica, Arial, sans-serif;
font-weight: 600;
text-transform: uppercase;
text-align: center;
}
.headertekstrotate {
position: relative;
}
.headertekstrotate span {
animation: clock 12s linear infinite 0s;
-ms-animation: clock 12s linear infinite 0s;
-webkit-animation: clock 12s linear infinite 0s;
position: absolute;
left: 0;
top: 0;
width: 100%;
opacity: 0;
}
.headertekstrotate span:nth-child(2) {
animation-delay: 4s;
-ms-animation-delay: 4s;
-webkit-animation-delay: 4s;
}
.headertekstrotate span:nth-child(3) {
animation-delay: 8s;
-ms-animation-delay: 8s;
-webkit-animation-delay: 8s;
}
#keyframes clock {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
25% {
opacity: 1;
}
30% {
opacity: 0;
}
80% {
opacity: 0;
}
100% {
opacity: 0;
}
}
<h2 class="headertekst">
<div class="headertekstrotate">
<span>Interlaser is short.</span>
<span>Interlaser is very very long.</span>
<span>Interlaser is professioneel.</span>
</div>
</h2>
Try to something like this.
.headertekst{
left: 0;
right: 0;
width: 100%;
text-align: center;
}
<h2 class="headertekst">This is Heading</h2>
try this
.headertekst
{
text-align:center;
width:100%;
}
.headertekst
{
text-align:center;
width:100%;
}
<h2 class="headertekst">This is center text</h2>
Simply change the Css properties to this:
.headertekst {
width: 100%
display: inline-block;
overflow: hidden;
text-align: center;
}
Reason: Sometimes text-align does not works if there is no width set. And overflow should always be kept hidden in these cases. display: inline-block As its name says: it displays the element in a line in a block. And finally, text-align: center it aligns the text to center.
I'm trying to achieve a typing effect with multiple lines in CSS.
This was a good reference point I followed:
CSS animated typing
https://css-tricks.com/snippets/css/typewriter-effect/
Now my desired effect is that the first border-right's visibility be hidden once the first blinking cursor's animation ends. A the border-right is still on screen after the animation ends and I want it not to be visible. (As if enter button on a keyboard was pressed.) How would I go about that?
https://jsfiddle.net/6567onn8/5/
.typewriter h1 {
text-align: center;
overflow: hidden;
font-size: 100%;
border-right: .15em solid #fff;
white-space: nowrap;
/* keeps content in one line */
letter-spacing: .15em;
animation: typing 2.5s steps(22, end), blink-caret .75s step-end;
}
.typewriter h2 {
font-size: 100%;
white-space: nowrap;
overflow: hidden;
border-right: .15em solid black;
-webkit-animation: typing 2s steps(26, end), blink-caret 1s step-end infinite;
-webkit-animation-delay: 3s;
-webkit-animation-fill-mode: both;
-moz-animation: typing 2s steps(26, end), blink-caret 1s step-end infinite;
-moz-animation-delay: 3s;
}
/* The typing effect */
#keyframes typing {
from {
width: 0
}
to {
width: 9em;
}
}
#keyframes blink-caret {
from, to {
border-color: transparent
}
50% {
border-color: #000;
}
}
<div class="typewriter">
<h1>Hi. I'm Andy.</h1>
<h2>I love learning.</h2>
</div>
Just take out infinite
.typewriter h1 {
text-align: center;
overflow: hidden;
font-size: 100%;
border-right: .15em solid #fff;
white-space: nowrap;
/* keeps content in one line */
letter-spacing: .15em;
animation: typing 2.5s steps(22, end), blink-caret .75s step-end;
}
.typewriter h2 {
font-size: 100%;
white-space: nowrap;
overflow: hidden;
border-right: .15em solid black;
-webkit-animation: typing 2s steps(26, end), blink-caret 1s step-end;
-webkit-animation-delay: 3s;
-webkit-animation-fill-mode: both;
-moz-animation: typing 2s steps(26, end), blink-caret 1s step-end;
-moz-animation-delay: 3s;
}
/* The typing effect */
#keyframes typing {
from {
width: 0
}
to {
width: 9em;
}
}
#keyframes blink-caret {
from, to {
border-color: transparent
}
50% {
border-color: #000;
}
}
<div class="typewriter">
<h1>Hi. I'm Andy.</h1>
<h2>I love learning.</h2>
</div>
body{
margin: 0;
font-family: 'Pacifico', cursive;
}
.blackboard-wrapper {
width: 100vw;
height: 100vh;
background-image: repeating-linear-gradient(to bottom,#26180B 70%,#362418 77%,#77736A 78%,#655444 78%);
}
.black-board {
height: 360px;
width: 800px;
transform: translateY(70px);
margin: 0 auto;
background-image: repeating-linear-gradient(to bottom,#000000 77%,#111111 78%,#222222 77%,#000000 78%);
border-width: 15px;
border-style: groove;
border-color: #2E1E11;
position: relative;
color: #ffffff;
}
.date {
position: absolute;
left: 15px;
top: 10px;
}
.date > span {
display: block;
margin-bottom: 5px;
}
.black-board::before {
position: absolute;
left: 0;
content: "";
right: 0;
background-color: #afafaf;
height: 2px;
top: 94px;
}
.topic {
position: absolute;
top: 28px;
left: 50%;
transform: translateX(-50%);
text-decoration: underline;
word-spacing: 8px;
}
.writing {
position: absolute;
top: 120px;
left: 15px;
right: 15px;
bottom: 15px;
}
.writing::after,
.writing::before {
position: absolute;
letter-spacing: 2px;
font-size: 30px;
animation-name: write;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: cubic-bezier(.7,.45,.97,.36);
}
.writing::before{
font-size: 25px;
content:"This is cool NAAA???";
top: 70px;
color: #1FBEA6;
animation-name: write2;
animation-duration: 2s;
animation-iteration-count: 1;
animation-timing-function: cubic-bezier(.7,.45,.97,.36);
}
#keyframes write{
0%{content:"";}
3%{content:"V_";}
6%{content:"VI_";}
9%{content:"VIK_";}
12%{content:"VIKA_";}
15%,25%{content:"VIKAS";}
28%{content:"VIKA_";}
31%{content:"VIK_";}
34%{content:"VI_";}
37%{content:"V_";}
40%,50%{content:"";}
53%{content:"P_";}
56%{content:"PA_";}
59%{content:"PAT_";}
62%{content:"PATE_";}
65%,75%{content:"PATEL";}
78%{content:"PATE_";}
81%{content:"PAT_";}
84%{content:"PA_";}
88%{content:"P_";}
91%,100%{content:"";}
}
#keyframes write2{
0%{content:"";}
5%{content:"T_";}
10%{content:"Th_";}
15%{content:"Thi_";}
20%{content:"This_ ";}
25%{content:"This i_";}
30%{content:"This is_";}
35%{content:"This is_ ";}
40%{content:"This is c_";}
45%{content:"This is co_";}
50%{content:"This is coo_";}
55%{content:"This is cool_";}
65%{content:"This is cool N_";}
70%{content:"This is cool NA_";}
75%{content:"This is cool NAA_";}
80%{content:"This is cool NAAA";}
85%{content:"This is cool NAAA?";}
90%{content:"This is cool NAAA??";}
95%{content:"This is cool NAAA???";}
100%{content:"This is cool NAAA???";}
}
<link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet">
<div class="blackboard-wrapper">
<div class="black-board">
<div class="date">
<span>DATE</span>
<span>25|oct|2018</span>
</div>
<div class="topic">TYPING EFFECT USING CSS</div>
<div class="writing"></div>
</div>
</div>
https://codepen.io/Vikaspatel/pen/mzarrO
.wrapper {
height: 100vh;
/*This part is important for centering*/
display: flex;
align-items: center;
justify-content: center;
}
.typing-demo {
width: 22ch;
animation: typing 2s steps(22), blink .5s step-end infinite alternate;
white-space: nowrap;
overflow: hidden;
border-right: 3px solid;
font-family: monospace;
font-size: 2em;
}
#keyframes typing {
from {
width: 0
}
}
#keyframes blink {
50% {
border-color: transparent
}
}
<div class="wrapper">
<div class="typing-demo">
This is a typing demo.
</div>
</div>
Easiest way of doing it in CSS.