使用 CSS 实现打字机效果
一位Reddit 用户在 CSS 频道询问是否有办法实现打字机效果。一些人推荐Geoff Graham 的《CSS Tricks》文章(其中包含 CSS 和 JS 的不同版本),还有更多人建议使用 JavaScript 或一些 JS 库/模块……而我则尝试自己实现一个纯 CSS 版本:
这个想法是让content
伪元素的属性动起来,比如::before
一次显示一个字符。然后,我们可以使用该::after
元素来显示闪烁的插入符号。
该content
属性是可离散动画的。这意味着不会有过渡效果(如果能实现就更好了),但它仍然会“逐步”地进行动画处理,这正是我们想要的。
它并非完美,但足够吸引眼球,而且与类似的纯 CSS 解决方案相比,它有一些不错的优势。此外,它还具有一些可定制性(插入符号可以更改颜色和大小),我尽力让它尽可能易于使用。
主要问题在于计算步骤以及它们必须发生的时间。为了简化和概括这个过程,我创建了一个简短的 JavaScript 代码片段,用于生成任意单词集的动画步骤……可惜的是,虽然它在大多数情况下都能正常工作,但我的计算有误,有时会失败。(一旦确认它正常工作,我会添加链接。)
优点和缺点
这种方法的优点:
- 它是多行的:许多纯 CSS 打字机动画仅适用于单行/单字。这个动画也可以用于多行。
- 它不会剪切字母/单词:每个字母都是单独添加的,而不是通过溢出来隐藏,从而可能部分显示它们(就像在其他解决方案中发生的那样)。
- 无需等宽字体:与上一点相关。其他动画只适用于等宽字体,以避免剪切单词/字母的问题。这个动画也适用于非等宽字体。
这种方法的缺点:
- 需要一些可访问性提升(见下文):在我看来,大多数执行此操作的动画(CSS 或 JS)都有这个问题。
- 这涉及到大量的代码:CSS动画的行数和字母总数一样多……而且编写起来非常痛苦:需要进行大量的计算!所以我创建了一个小脚本来简化这个过程。
- 并非所有浏览器都支持:某些浏览器不支持伪元素的动画(最明显的是 Mac 和 iOS 上的 Safari)。
为了解决最后一部分,或许我可以使用steps()
计时功能。但最终,它也需要一些(更简单的)计算。
无障碍设施
我们将采取一些措施来提高此动画的可访问性...其中之一就是删除动画😅
首先,虽然视力正常的用户可以看到文本的变化,但辅助技术 (AT) 用户可能看不到。例如,屏幕阅读器用户无法获得文本变大/缩小的信息——这很麻烦,因为那会很麻烦!
为了避免获得标题的一半描述,我们应该aria-label
向容器中添加具有完整描述的描述。
<h1 aria-label="I'm a developer, writer, reader, and human.">
I'm a <span class="typewriter"></span>
</h1>
如果没有aria-label
,屏幕阅读器会将标题读为“我是”;有了aria-label
,它们会读为“我是开发人员、作家、读者和人类。 ”,这样要好得多。
为了让组件更容易访问,我们可以做的另一件事是移除实际的动画。如果用户启用了“减少动画”设置,我们应该停止插入符号的闪烁,使其保持固定,并可能显示完整的单词,而不是逐个字母地显示。为此,CSS 使用了prefers-reduce-motion
媒体查询:
@media (prefers-reduced-motion) {
/* let the caret be fixed instead of blinking */
.typewriter::after {
animation: none;
}
/* replace the letter popup for a shorter animation */
@keyframes sequencePopup {
0%, 100% { content: "developer"; }
25% { content: "writer"; }
50% { content: "reader"; }
75% { content: "human"; }
}
.sequencePopup::before {
content: "developer";
animation: none;
}
}
我们并没有完全移除动画;只是用一个更易于访问的动画替换了它。并非所有动画都是不好的,“减少动效”并不意味着“没有动效”。
文章来源:https://dev.to/alvaromontoro/typewriter-effect-with-css-38im