CSS animated typing

2019-07-20 22:16发布

I'm trying make an animation as if I was typing. To achieve this I'm using CSS animation 'steps'.

The animation itself works just fine. However, if I want to animate multiple lines of text, they all start playing at the same time. Wich isn't giving me the desired effect. (Tried using <br> in a single <h1>, wich cut off the text, but again started the animations simultaniously.)

To counter this, I put the next line of text in an <h2> and set an animation-delay for every line of text. Wich works, but the text is visible before the animation starts.

I want the text to be hidden until the animation starts playing, to really get that 'live typing' effect.
Anyone got any ideas on how I can achieve this?

HTML

<div class="content"> 
    <h1>Hi there! My name is Jeff.</h1>
    <h2>And I create cool stuff.</h2>
</div>

CSS

.content h1 {
    background:white;
    opacity:0.7;
    white-space:nowrap;
    overflow:hidden;
    border-right: 3px solid black;
    -webkit-animation: typing 2s steps(26, end), 
                        blink-caret 1s step-end 2s;
}
.content h2 {
    background:white;
    opacity:0.7;
    white-space:nowrap;
    overflow:hidden;
    border-right: 3px solid black;
    -webkit-animation: typing 2s steps(26, end), 
                        blink-caret 1s step-end infinite;
    -webkit-animation-delay:3s;
}

@-webkit-keyframes typing {
    from { width: 0; }
    to { width:400px; }
}

@-webkit-keyframes blink-caret {
    from, to { border-color: transparent }
    50% { border-color: black }
}

jsFiddle

Thanks in advance.

4条回答
混吃等死
2楼-- · 2019-07-20 22:51

p
{
  font:500 22px consolas;    
  width:20ch;
  white-space:nowrap;
  overflow:hidden;
  animation:type 5s steps(20) infinite;
}
@keyframes type
{
  0%{ width:0; } 
}
<p>Text Type Animation</p>

查看更多
姐就是有狂的资本
3楼-- · 2019-07-20 22:52

The simplest solution is to add:

animation-fill-mode:both;

to your h2 (with the necessary prefixes). That way, you aren't setting it to a zero width outside of your animation, so browsers that don't support this CSS will display the heading (which I guess is what you're after). See this fiddle.

The animation-fill-mode:

specifies how a CSS animation should apply styles to its target before and after it is executing

Setting it to both in this instance means that your h2 will have a width of 0 before it starts executing, and a width of 400px after.

查看更多
一纸荒年 Trace。
4楼-- · 2019-07-20 23:02

As the comments already include a solution, perhaps this might be another way of doing it - by using timeouts and setting visibility: hidden at the beginning (For simplification I just used jQuery to set the visiblitiy).

Include the following CSS rule:

.content {
    visibility: hidden;
}

As JavaScript you would have:

window.setTimeout(function() {
    $('#contentdiv h1').css('visibility', 'visible');
}, 100);

window.setTimeout(function() {
    $('#contentdiv h2').css('visibility', 'visible');
}, 3100);

See the jsFiddle

查看更多
戒情不戒烟
5楼-- · 2019-07-20 23:03

Not quite the OP's question, but in case someone else finds this useful:

I wanted to be able to typing-animate a pararaph of text, a single <p> tag which might contain text that would wrap, and produce an unknown number of actual lines. Applying a simple linear animation to the p tag itself wouldn't work, so instead, I took the approach of having several "hider" elements that would cover the paragraph of text, each one line high, and then I would animate each of those so they would shrink away, reveal characters from the line of text beneath them.

The HTML looks like this:

<div class="container">
<!-- container div is required to set absolute positions within it, so that .typing and .hiders exactly overlap -->

  <p class="typing">
    This paragraph of text will be animated 
    with a "typewriter" style effect, and it 
    will continue to work even if it splits across 
    multiple lines.  Well, in this case, up to a 
    maximum of 5 lines, but you get the picture.
  </p>

  <div class="hiders">
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
  </div>

</div>

You need a container, and position the .typing element and the .hiders using absolute so that they're on top of each other:

.container {
  position: relative;
  font-family: Consolas, monospace;  
}
.typing {
  position: absolute;
  top: 0;
  margin: 0;
  z-index: -1;
}
.hiders {
  margin: 0;
  position: absolute;
  top: 0;
  width: 100%;
}

And the animation gets applied to each p inside the .hiders:

.hiders p {
  position: relative; 
  clear: both; 
  margin: 0;
  float: right; /* makes animation go left-to-right */
  width:0; /* graceful degradation: if animation doesn't work, these are invisible by default */
  background: white; /* same as page background */
  animation: typing 2s steps(30, end);
  animation-fill-mode: both;  /* load first keyframe on page load, leave on last frame at end */
}

.hiders p:nth-child(2) {
  animation-delay: 2s;
}
.hiders p:nth-child(3) {
  animation-delay: 4s;
  /* etc */

Here's the final fiddle:

https://jsfiddle.net/hjwp/514cLzxn/

Original credit for inspiration: Lea Verou

查看更多
登录 后发表回答