CSS——文字打字机效果

CSS------文字打字机效果

本文通过纯 CSS 实现文字的打字机效果,然后借助 JS 实现了扩展。

typewriter

基本思路

使用伪元素覆盖原文字,并且使用伪元素模拟闪烁的光标效果。

具体流程

首先是一些基本的设置

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文字打字机效果</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    body {
      /* 防止宽度过小,导致 h1的宽度与视口的最小宽度一致,以至于效果出现差错 */
      min-width: fit-content;
      width: 100vw;
      height: 100vh;
      background-color: hsl(280, 50%, 30%);
      display: flex;
      justify-content: center;
      align-items: center;
      /* 设置等宽字体 */
      font-family: monospace;
      /* 不要滚动条 */
      overflow: hidden;
    }


    #h1 {
      position: relative;
      color: #fff;
      text-align: center;
      font-size: 2.5rem;
      letter-spacing: .2em;
      text-transform: uppercase;
      /* 防止文字换行 */
      text-wrap: nowrap;
      /* 加载完成之后隐藏后面的输入 */
      overflow: hidden;
    }
    
    #h1::before,
    #h1::after {
      content: "";
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      background-color: hsl(280, 50%, 30%);
    }
  </style>
</head>

<body>
  <h1 id="h1">I'm lazy-sheep-king!</h1>
</body>

</html>

#h1::before 遮住原文字,然后设置关键帧逐步显示,#h1::after 用于表示光标。

这里有一些需要注意的点:

首先是 body 设置为 min-width: fit-content;,这里是防止缩放视口导致视口宽度小于原来文本的宽度时,文本的宽度也会跟着缩小为视口的宽度;

然后是设置等宽字体 font-family: monospace;,这个是关键,每一步的步长就是每个字母的宽度;

此外是 h1 标签的 ext-wrap: nowrap;,这里是防止宽度过小导致文字换行;

最后是 h1 标签的 overflow: hidden;,这个可有可无,如果加上,那么最后的光标就会隐藏,如果不加,那么文字加载完成之后的光标就会继续闪烁。

设置关键帧

首先设置移动关键帧:

css 复制代码
#h1::before {
  animation: typewriter 5s steps(20) forwards;
}

#h1::after {
  width: 5px;
  border-radius: 1em;
  background-color: hsl(60, 100%, 35%);
  animation: typewriter 5s steps(20) forwards
}

@keyframes typewriter {
  to {
    left: 100%;
  }
}

首先解释 steps(20),效果为该动画分为多少步完成,一步一顿,因为有20个字符,所有就分为20步完成。

然后是 animation-fill-mode: forwards,这个是动画结束之后,元素的状态,这里停留到最后一帧。

设置光标闪烁帧

css 复制代码
#h1::after {
  width: 5px;
  border-radius: 1em;
  background-color: hsl(60, 100%, 35%);
  animation: typewriter 5s steps(20) forwards,
    flashing 0.25s infinite alternate;
}

@keyframes flashing {
  to {
    opacity: 0;
  }
}

通过改变透明度,表示光标的闪烁效果。

同一个元素可以添加多个动画效果,用逗号","隔开。

扩展性

为了增强扩展性,可以使用js进行一些处理。

js 复制代码
<script>
  // 获取标签
  const h1 = document.querySelector('#h1');
  // 获取文本长度
  const length = h1.innerHTML.length;
  // 使用自定义属性变量传递到 CSS中
  h1.style.setProperty('--length', length);
</script>

这样我们动态计算文本的长度,并使用自定义属性变量传递到 CSS中,将steps(20)中的参数换位var(--length),但需要注意的是,即使是等宽的字体,其中文和英文的宽度还是有区别的,这里仅考虑为纯英文或纯中文的情况(如果中英文混合的话,可以考虑使用<span>标签包裹每个单独的单词/汉字,然后设置统一的宽度,最后使用js添加与计算)。

结语

创作不易,谢谢支持;如有错误,恳请指出,希望与大家共同进步!

源码

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文字打字机效果</title>
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }

    body {
      /* 防止宽度过小,导致 h1的宽度与视口的最小宽度一致,然后使效果出现差错 */
      min-width: fit-content;
      width: 100vw;
      height: 100vh;
      background-color: hsl(280, 50%, 30%);
      display: flex;
      justify-content: center;
      align-items: center;
      /* 设置等宽字体 */
      font-family: monospace;
      /* 不要滚动条 */
      overflow: hidden;

    }


    #h1 {
      position: relative;
      color: #fff;
      text-align: center;
      font-size: 2.5rem;
      letter-spacing: .2em;
      text-transform: uppercase;
      /* 防止文字换行 */
      text-wrap: nowrap;
      /* 加载完成之后隐藏后面的输入 */
      overflow: hidden;
    }

    #h1::before,
    #h1::after {
      content: "";
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      background-color: hsl(280, 50%, 30%);
    }

    #h1::before {
      animation: typewriter 5s steps(20) forwards;
    }

    #h1::after {
      width: 5px;
      border-radius: 1em;
      background-color: hsl(60, 100%, 35%);
      animation: typewriter 5s steps(20) forwards,
        flashing 0.25s infinite alternate;
    }

    @keyframes typewriter {
      to {
        left: 100%;

      }
    }

    @keyframes flashing {
      to {
        opacity: 0;
      }
    }
  </style>
</head>

<body>
  <h1 id="h1">I'm lazy-sheep-king!</h1>
  <script>
    // 获取标签
    const h1 = document.querySelector('#h1');
    // 获取文本长度
    const length = h1.innerHTML.length;
    // 使用自定义属性变量传递到 CSS中
    h1.style.setProperty('--length', length);
    console.log(length);
  </script>
</body>

</html>
相关推荐
weedsfly1 小时前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户059540174461 小时前
AI Agent记忆测试踩坑实录:Mock骗了我一周,Mem0+pytest一招破局
前端·css
用户1733598075371 小时前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
IT_陈寒1 小时前
SpringBoot自动配置的坑,我爬了三天才出来
前端·人工智能·后端
Avan_菜菜8 小时前
AI 能写代码了,为什么我反而开始要求它先写文档?
前端·github·ai编程
爱勇宝12 小时前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
IT_陈寒16 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen16 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
牧艺16 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
红尘散仙17 小时前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust