前言
最近在重温《css权威指南》,看到第5章字体时font-family属性有一个关键字叫monospace,也就是等宽字体:每一个字符的宽度都是等宽的。
这个monospace字体,一开始就是因为技术局限性,打字机无法实现字母宽度自适应而使用的一种字体。
//代码块中使用了等宽字体,字母i的宽度与字母m的宽度是一样的。
var i = 'iiiiiiii';
var m = 'mmmmmmmm';
而在非代码块中:
var i = 'iiiiiiii';
var m = 'mmmmmmmm';
使用的就是宽度自适应的字体,字母i明显比字母m要窄。
那么这个属性的等宽特点有什么应用场景呢?
应用场景
我想到的一个应用场景就是利用宽度来实现具有打字效果的loading动画:
- 有闪烁的光标;
- 文本为loading...;
- 固定时间间隔显示一个字符;
- 能够循环显示。
实现效果
实现思路
首先是文档结构:
<!--只有一行p标签。-->
<p class="load-text">loading...</p>
其次是最重要的css代码:
/*光标动画*/
@keyframes caret {
50% {border-color: transparent;}
}
/*文本动画:从宽度为0开始*/
@keyframes text {
from {width: 0;}
}
.load-text {
width: 11ch;
margin: 0 auto;
overflow: hidden;
word-break: keep-all;
background: rgba(181, 219, 136,0.2);
color: #b1f1f3;
border-right: 3px solid #000000;
font: bold 400% monospace;
animation: caret 0.5s step-end infinite ,text 5s infinite steps(11);
}
最后是代码解释:
光标的实现
利用p标签的右边框,设置0.5s动画将其边框色改为transparent即可。
动态打字的实现
动态打字效果的本质就是p标签的宽度从0增加到文本的宽度时,其文本会逐个展示出来。那么如何控制每一次增加的正好是一个字符的宽度呢?
这就要说到两个关键的东西:font-family:monospace和ch长度单位。
monospace之前已经讲过了,而ch这个单位相信很多前端同行都没有听说过,按照标准,1ch就是当前字体环境中数字 0 的宽度,那么在字体为monospace的情况下,1ch就是所有字符的宽度。
理解了这两个东西,我们就可以在css中设置p标签的字体为monospace,同时宽度设置width:11ch,因为loading....一共有10个字符,但是关键帧应当有(0,1,2,3,4,5,……,10)一共11个,所以添加一个字符的宽度。
除了这两个关键属性外,就是样式的设置了。overflow:hidden;和word-break:keep-all;是为了防止中文字符在p标签宽度不够的情况下出现自动换行的bug。
animation:text 5s infinite steps(11);是利用了steps()值设定步长,因为一共11ch的长度,所以设定11个步长。然后设置infinite来实现无限循环。
注意:汉字的长度是2个字符长度,设定的步长和宽度要X2。
源码
我把源码放在自己的工具仓库了,欢迎star。
tools/loading
总结
我在写这篇文章之前,看过很多网上实现打字机效果的demo,大部分都是配合js或者jquery插件来实现,方法的使用范围较广,但是代码量较多。而实际上只需要利用monospace和ch长度单位就可以实现简单的打字机效果。所以说合理利用css的某些属性能够帮助我们减少一定的工作量。
题外话
这段时间,我也在看张鑫旭的博客,从2009年一直到2016年的每一篇文章,他理解的css和我理解的css真的是两个层面。不得不说我以前还是停留在表面,没有深入去思考css实现效果的原理和机制,跟资深的前端程序员比起来自己真是井底之蛙。希望以后能努力学习知识,有一天能够与这些大神共事。
非常感谢你能够看完这篇文章,如果有什么意见,欢迎在评论中指出。非常乐意与各位交流学习。