Skip to content

多行文本可以通过 steps() + width + overflow + white-space 来实现。

一、基础版:单行打字效果

html
<div class="typewriter">
  <p>你好,这是一个打字效果的演示。</p>
</div>
css
.typewriter {
  width: fit-content; /* 让容器适应内容 */
  font-family: 'Courier New', monospace; /* 等宽字体,便于精确控制 */
}

.typewriter p {
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  border-right: 2px solid; /* 模拟光标 */
  animation: 
    typing 4s steps(20, end) forwards, /* 20需替换为实际字符数 */
    blink-caret 0.75s step-end infinite;
}

@keyframes typing {
  from { width: 0 }
  to { width: 40ch } /* 使用ch单位(字符宽度)更精确 */
}

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

原理

核心是:

steps(n)

把动画拆成 n 步,就像一个个字符出现。

width: 40ch

ch = 字符宽度单位。

二、多行文本打字效果(推荐方案)

纯 CSS 多行需要 控制高度逐步展开

HTML

html
<div class="typing-multi">
Hello World
This is CSS typing effect
Support multiple lines
Pure CSS animation
</div>

CSS

css
.typing-multi {
  width: 30ch;
  overflow: hidden;
  border-right: 2px solid #000;
  white-space: pre-wrap;
  line-height: 1.6;
  
  animation:
    typing-multi 6s steps(120) forwards,
    blink .8s infinite;
}

@keyframes typing-multi {
  from {
    width: 0;
  }
  to {
    width: 30ch;
  }
}

@keyframes blink {
  50% {
    border-color: transparent;
  }
}

三、真正多行逐行输出

如果你希望 一行一行输出

HTML

html
<div class="container">
  <p class="line">Hello World</p>
  <p class="line">This is CSS typing effect</p>
  <p class="line">Support multiple lines</p>
  <p class="line">Pure CSS animation</p>
</div>

CSS

css
.line {
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  border-right: 2px solid transparent;
}

.line:nth-child(1) {
  animation: typing 2s steps(20) forwards, cursor 0.5s step-end 4 alternate;
}

.line:nth-child(2) {
  animation: typing 2s steps(25) 2s forwards, cursor 0.5s step-end 4 alternate 2s;
}

.line:nth-child(3) {
  animation: typing 2s steps(22) 4s forwards, cursor 0.5s step-end 4 alternate 4s;
}

.line:nth-child(4) {
  animation: typing 2s steps(22) 6s forwards, cursor 0.5s step-end infinite alternate 6s;
}

@keyframes typing {
  from { width: 0; }
  to   { width: 100%; }
}

@keyframes cursor {
  from { border-right-color: black; }
  to   { border-right-color: transparent; }
}

效果:

Hello World

This is CSS typing effect

Support multiple lines

Pure CSS animation

逐行打字。

四、企业级优化版本(推荐)

适合 React / Vue / AI Chat UI

css
.typing {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  border-right: 2px solid;
  width: 0;
  animation: typing var(--time) steps(var(--steps)) forwards;
}

@keyframes typing {
  to {
    width: 100%;
  }
}

HTML

html
<div class="typing" style="--time:3s;--steps:30">
  Hello this is typing effect
</div>

优势:

  • 动态控制字符数
  • 组件化
  • 适合 AI Chat

五、AI Chat 场景的更真实方案

ChatGPT / Claude 一样的效果:

CSS + JS

html
<div id="app">
  <div id="text"></div>
</div>
css
#text {
  font-size: 18px;
  line-height: 1.6;
  /* border-right: 2px solid black; */
  display: inline-block;
  padding-right: 4px;
  animation: blink 1s infinite;
   white-space: pre-wrap;
}
#text::after {
  content: "|";
  margin-left: 2px;
  animation: blink 1s infinite;
}

@keyframes blink {
  50% {
    border-color: transparent;
  }
}

JS 控制字符流:

js
function typing(el, text, speed = 40) {
  let i = 0
  let last = 0

  function frame(time) {
    if (time - last > speed) {
      el.textContent += text[i]
      i++
      last = time
    }

    if (i < text.length) {
      requestAnimationFrame(frame)
    }
  }

  requestAnimationFrame(frame)
}

const el = document.getElementById("text")

typing(
  el,
  "Hello World!\nThis is a typing effect demo.\nSupport multiple lines.",
  60
)

六、纯 CSS 的限制

纯 CSS 有几个限制:

限制原因
不能根据字符数自动计算 stepsCSS 不知道文本长度
多行控制困难需要手动 delay
动态文本不行CSS 静态

所以 AI Chat 必须 JS 控制

七、如何实现打字效果?

如果是静态文本可以用 CSS steps() 实现:

  • overflow:hidden
  • width
  • steps(n)

如果是动态 AI 流式文本,需要 JS 控制字符流,或者直接使用 SSE/WebSocket 的 chunk 更新。