自定义字体知识整理

4,957 阅读6分钟

自定义字体

CSS3引入的@font-face,让我们为我们的文本引入自定义字体,指定的字体可以从远程服务器或者用户本地安装的字体加载。@font-face规则不仅仅可以使用在CSS的顶层,还可以用在任何CSS条件组规则中。

一般我们使用只需要向下面这样定义就可以:

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
       url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
}

除了上面两个数户型,它还有一些列的属性,来指定字体的具体属性,可以参考MDN的文档

字体类型

常见的字体类型有以下几种:

  • .ttf:True Type,是Windows和Mac系统最常用的字体格式,它可以任意缩放和旋转不会出现锯齿
  • .otf:Open Type,是可缩放性的电脑字体类型,是微软与Adobe共同开发用来替代TrueType的新字形
  • .eot:Embedded Open Type,微软开发的嵌入字体格式
  • .woff,Web Open Font Format,专门为了We设计的字体格式标准,是对True Type、Open Type等字体格式的封装,并针对网络使用进行了优化
  • .svg,Scalable Vector Graphics Fonts,使用SVG来呈现字体(.svgz是使用了Gzip压缩的SVG字体)

目前现代浏览器基本都支持.ttfotfwoff的字体格式,如果为了保证兼容不同的浏览器,一般会同时指定多个格式

@font-face {
  font-family: 'myFont';
  src: url('myFont.eot'); /* IE9 Compat Modes */
  src: url('myFont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 
       url('myFont.woff') format('woff'), /* Modern Browsers */;
}

实际使用

在字体天下这个网站,随便找到了一个字体PangMenZhengDaoQingSongTi-2.otf下载下来,放到本地目录中。

因为字体是我随便下载的,只有otf这种格式。

然后在CSS文件中,首先声明我自定义的字体名和位置:

@font-face {
  font-family: 'Secret Font';
  src: url('../assets/fonts/PangMenZhengDaoQingSongTi-2.otf');
}

然后在一个类中使用自定义字体:

.special {
  font-family: 'Secret Font', sans-serif; /* 使用 @font-face 自定义的字体 */
  font-size: 40px;
}

效果:

自定义图标字体(IconFont)

在ElementUI中我们经常使用的Icon图标实际上就是使用了自定义字体的技术,实际上它就是把一些简单的图标制作成为了字体,然后让图标变成和文字一样,可以通过CSS去改变颜色、大小等,非常方便。

比较常用的是阿里巴巴推出的IconFont ,在上面找到我们想要使用的图标之后,有下面几种引用方法:

(1)直接下载

直接将图标保存为SVG、PNG等格式,然后在项目中引入,这种引用方式一般适合图标引用很少,且不需要维护的场景,比如做Demo页、活动页等

(2)unicode引用

unicode是字体在网页端最原始的应用方式,兼容性好,可以按照字体的方式去动态调整图标大小,颜色。不支持多色,使用时需要首先将选好的图标放到一个项目中,然后拷贝项目下面生成的的font-face

@font-face {
  font-family: 'iconfont';
  src: url('iconfont.eot');
  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
    url('iconfont.woff') format('woff'),
    url('iconfont.ttf') format('truetype'),
    url('iconfont.svg#iconfont') format('svg');
}

然后在CSS定义使用IconFont的样式:

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -webkit-text-stroke-width: 0.2px;
  -moz-osx-font-smoothing: grayscale;
}

然后找到图标对应的字体unicode编码,它指定的文字在我们自定义字体中对应的不是一个文字,而是一个图标,所以就能将这个图标应用于页面了:

<i class="iconfont">&#x33;</i>

(3)font-class引用

这种方式使用时的一个不方便之处就是,unicode码不直观,语义不明确,所以可以使用font-class来引入。

它本质上和上一种方式的引用是相同的,只是系统帮我们在CSS中定义了图标的unicode对应的CSS类,所以需要先引入项目下面生成的CSS代码:

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css

然后就可以直接使用图标的类名来引用图标了:

<i class="iconfont icon-xxx"></i>

(4)symbol引用

这种引用方式实际上和自定义字体没什么关系了,它实际上是通过SVG来引入,做了一个SVG的集合,它支持多色图标,并且通过一些技巧让我们仍然可以通过font-sizecolor来调整样式。

但是它兼容性较差,不支持IE9之前的浏览器,并且浏览器渲染SVG的性能比较差。

引入的时候需要拷贝项目下的JavaScript代码:

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js

然后加入通用CSS代码,引入一次即可:

<style type="text/css">
  .icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
}
</style>

然后挑选类名,通过<svg><use>标签引入图标:

<svg class="icon" aria-hidden="true">
  <use xlink:href="#icon-xxx"></use>
</svg>

加密自定义字体

打开大众点评的网站,随表找一家店铺,复制它的评论数:

复制的结果竟然是:

再打开控制台,找到对应的HTML代码:

在控制台也是乱码。查看网页的源代码,可以看出数字对应的是一个unicode编码:

<d class="num">&#xf72e;</d>

它有一个num的类:

.num {
  font-family: 'PingFangSC-Regular-num';
}

如果将这个类取消,那么页面上的数字也都会出现乱码。一切的秘密都是在这个类上。

这个类就是我们上面提到的自定义字体,在大众点评的静态资源中,找到了一份样式文件,就定义了这个字体:

@font-face {
  font-family: "PingFangSC-Regular-hours";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.woff");
}

.hours {
  font-family: 'PingFangSC-Regular-hours';
}

@font-face {
  font-family: "PingFangSC-Regular-address";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.woff");
}

.address {
  font-family: 'PingFangSC-Regular-address';
}

@font-face {
  font-family: "PingFangSC-Regular-dishname";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/53426607.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/53426607.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/53426607.woff");
}

.dishname {
  font-family: 'PingFangSC-Regular-dishname';
}

@font-face {
  font-family: "PingFangSC-Regular-review";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/52e0505f.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/52e0505f.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/52e0505f.woff");
}

.review {
  font-family: 'PingFangSC-Regular-review';
}

@font-face {
  font-family: "PingFangSC-Regular-num";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/0b355749.woff");
}

.num {
  font-family: 'PingFangSC-Regular-num';
}

@font-face {
  font-family: "PingFangSC-Regular-shopdesc";
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.eot");
  src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.eot?#iefix") format("embedded-opentype"), url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/aa7e2f36.woff");
}

.shopdesc {
  font-family: 'PingFangSC-Regular-shopdesc';
}

可以看出它定义了多个自定义字体,并且为不同的类加载不同的字体,数字的类是.num,它对应的自定义字体就是PingFangSC-Regular-num

它做的这一切都是为了防爬虫,因为对于大众点评来说它的这些数据就是它的核心资产,如果被网络爬虫爬走,那是巨大损失,它的优势也就不复存在。所以大众点评和众多的网络爬虫制造者之间展开了一场异常艰苦的攻防战。

它使用了自定义字体,但是还不足以达到上面的效果,它使用了加密自定义字体技巧,这是一种CSS加密方式,是一种应用广泛的反爬技术。

字体加密的原理是,用凯撒加密的方式将明文(下图的原文)替换为密文(下图的阴书),加密的密钥(也就是下图字验)就是上面font-face声明的自定义字体,加密好之后,HTML源码中是密文,使用自定义字体作为密钥进行CSS解密,渲染在页面上的就是解密后的正常的明文了

参考