1

This CSS makes the text appear with a typewriter effect. However the issue is that because of the white-space: nowrap in the CSS it only shows the top line.

So if I have text in a single <p> element that covers 4 lines, only the top line gets shown.

See the codepen for example.

p{
  color: lime; 
  font-family: "Courier";
  font-size: 20px;
  margin: 10px 0 0 10px;
  white-space: nowrap;
  overflow: hidden;
  width: 100%;
  animation: type 4s steps(60, end);
}

@keyframes type{ 
  from { width: 0; } 
} 

Are there any JS based solutions if it is not possible with pure CSS? I would like to not have to try to break up a paragraph into several <p> especially since the point at which there is a line break would get messed up when the width changed.

Harry
  • 87,580
  • 25
  • 202
  • 214
Badrush
  • 1,247
  • 1
  • 17
  • 35
  • The thing with animations like this is that if you remove the `white-space: nowrap`, it won't work like a typewriter effect because all four lines will start getting typed at the same time (as only width is being animated). You need to restrict yourself to a single line (or) use multiple `p` elements for each line. – Harry May 09 '16 at 05:48
  • yes you will need to use multiple lines http://codepen.io/victorfdes/pen/jqdzZz or you will need JS – Vitorino fernandes May 09 '16 at 05:53
  • Is there a way to automatically break a paragraph into those spans? I am okay using JS/Jquery. – Badrush May 09 '16 at 06:05
  • 2
    thats ok harry :D @Badrush check this http://stackoverflow.com/questions/4147080/can-i-wrap-each-line-of-multi-line-text-in-a-span – Vitorino fernandes May 09 '16 at 06:10
  • 2
    or you can use something like this https://jsfiddle.net/victor_007/4jy6xjr9/ – Vitorino fernandes May 09 '16 at 06:15
  • 2
    Nice one that @Vitorinofernandes :) – Harry May 09 '16 at 06:19
  • @Vitorinofernandes That one works great, but I dont see the animation keyframes in the CSS yet it still works... how? – Badrush May 09 '16 at 06:36
  • 1
    @Badrush: That one uses JS to get only the first character, first two, first three (and so on) from the entire content and print them using a loop (with `setTimeout`). The loop goes on till the entire content is printed. – Harry May 09 '16 at 06:38
  • Nice. Cheers! You can post that as an answer. – Badrush May 09 '16 at 13:45

3 Answers3

3

So if I have text in a single <p> element that covers 4 lines, only the top line gets shown.

Based on the above statement, I assume that the question is about text spanning multiple lines even when the maximum possible width is given to the element (that is, changing just the width is not an option).

As I had mentioned in my comment, the thing with animations like this is that if you remove the white-space: nowrap, it won't work like a typewriter effect because the full text will start getting typed at the same time (as only the width is being animated) and it will result in a weird animation because when the width is small the text will wrap-around and when it increases the text will also move to previous lines.

The text needs to be restricted to a single line or it should be split into multiple p tags like in the below snippet. If neither of these can be done then you should look at using JavaScript (or any library).

body {
  background: #000;
  padding-top: 10px;
  width: 500px;
  border: solid white 1px;
}
p {
  color: lime;
  font-family: "Courier";
  font-size: 20px;
  margin: 10px 0 0 10px;
  white-space: nowrap;
  overflow: hidden;
  width: 0;
  animation: type 4s steps(60, end) forwards;
}
p:nth-child(2) {
  animation-delay: 4s;
}
p:nth-child(3) {
  animation-delay: 8s;
}
p a {
  color: lime;
  text-decoration: none;
}
span {
  animation: blink 1s infinite;
}
@keyframes type {
  to {
    width: 100%;
  }
}
@keyframes blink {
  to {
    opacity: .0;
  }
}
::selection {
  background: black;
}
<p>hi folks, this is typing animation using</p>
<p>CSS. But on the second line it never</p>
<p>shows up. The other lines get cut off.</p>

The below is what would happen if you just remove white-space: nowrap. You can see how it does not work like a typewriter anymore.

body{
  background: #000;
  padding-top: 10px;
  width: 500px;
  border: solid white 1px;
} 

p{
  color: lime; 
  font-family: "Courier";
  font-size: 20px;
  margin: 10px 0 0 10px;
  overflow: hidden;
  width: 100%;
  animation: type 4s steps(60, end);
}

p:nth-child(2){
  animation: type2 8s steps(60, end);
}

p a{
  color: lime;
  text-decoration: none;
}

span{
  animation: blink 1s infinite;
}

@keyframes type{ 
  from { width: 0; } 
} 

@keyframes type2{
  0%{width: 0;}
  50%{width: 0;}
  100%{ width: 100; } 
} 

@keyframes blink{
  to{opacity: .0;}
}

::selection{
  background: black;
}
<p>hi folks, this is typing animation using CSS But on the second line it never shows up. The other lines get cut off.</p>

If you are open to using a fully JS based approach for achieving this animation then you could follow the method used in this Fiddle. It is a customized version of the Fiddle contributed by Akshay. It uses a loop (based on setInterval) and then modifies the content of the element in every iteration. First it fetches only the first character of the content, then the first two, first three and so-on till the content is fully printed. The looping and the interval makes it look as though it is being typed out.

You can control the speed of the typing, the delay that is added between the typing of lines by passing the required values in the function call.

Community
  • 1
  • 1
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Do you have any JS based solutions? I would like to not have to try to break up a paragraph into several

    especially since the point at which there is a line break would get messed up when the width changed.

    – Badrush May 09 '16 at 06:10
  • 1
    @Badrush: That's a wise option (to go fully with JS). [Here](https://jsfiddle.net/akshay7/kvvxu33v/8/) is a fiddle that my friend made for himself and you may find it useful. I will add this fiddle to my answer if he doesn't want to post it as a separate answer. – Harry May 09 '16 at 06:13
  • Hey, sometimes I start this effect but I want to stop the effect completely when someone clicks a button. How can I stop the code on a click else where? – Badrush May 09 '16 at 17:12
  • 1
    @Badrush: It is pretty simple. We'd just have to clear the interval when the user clicks anywhere on the page (I assume you are asking for the JS version). Its almost midnight here and I am responding through phone. Will give a sample in the morning :) – Harry May 09 '16 at 17:33
  • I tried it before I asked but clearTimeout was giving me issues. I used this variant of the code https://jsfiddle.net/victor_007/4jy6xjr9/ – Badrush May 09 '16 at 22:13
  • 1
    @Badrush: [Here](https://jsfiddle.net/4jy6xjr9/1/) is the updated fiddle. It stops the typing when you click anywhere on the document. – Harry May 10 '16 at 04:47
  • It worked great after some tinkering of where to best place it. I guess I wasn't cluing into the fact that I should give setTimeout a variable associated with it. If you dont mind, can you tell me the best way to stop the animation and have the text display in full immediately. So for example, if the typewriter text is appearing too slow and a person clicks a special button I want the full text to instantly appear so the user can read it as fast as they want. – Badrush May 11 '16 at 13:24
  • Worked like a charm. Very clever and clean solution. – Badrush May 11 '16 at 18:10
0

Try changing the the width of the body from 500px to 100%. Something like this below:

body{
  background: #000;
  padding-top: 10px;
  width: 100%;
  border: solid white 1px;
} 
Alex
  • 11
  • 3
  • Well my actual code, the width of the element holding the paragraph is fixed, so I can't just fit all the text on one line. – Badrush May 09 '16 at 06:08
0

You can try this one

body{
      background: #000;
      padding-top: 10px;
      width: 100%;
      border: solid white 1px;
    } 

    p{
      color: lime; 
      font-family: "Courier";
      font-size: 20px;
      margin: 10px 0 0 1px;
      white-space: nowrap;
      overflow: hidden;
      width: 100%;
      animation: type 4s steps(60, end);
    }

DEMO HERE

Ivin Raj
  • 3,448
  • 2
  • 28
  • 65