浏览器字体渲染的秘密

 

  说到web性能,前端工程师很自然地反应是yahoo的30+条优化规则。这些规则可以将网页加载从原来的几秒甚至十几秒较少到3s甚至1s以内。当一个完整界面展现在用户眼前时,内容就通过不同的字体、图片以及多媒体传达给用户。使用户在1s内看到网页和使用户留在网页上几分钟甚至几十分钟同样重要。字体作为内容承载信息的重要部分,若使用不“适当”的字体或者字体由于渲染等缘故对用户不友好,则会(有可能)造成不必要的用户流失。本文介绍浏览器的字体渲染,希望还未接触字体渲染的同事能通过本文对字体渲染有所了解。

  首先看下不同浏览器下的截图:


  很明显地看出,Chrome35截图中的非横竖笔画较IE11和Firefox30截图中的有明显的锯齿。

  理想的字体其边缘过渡平滑,而在屏幕上显示时,需要将字体栅格化(rasterization)为一个个像素点。采用黑白(black and white)渲染无法体现字体的细节之处,会造成了边缘呈现锯齿状(jagged)的不平滑。为了解决这个问题,字体渲染引擎采用了以下方法进行平滑(Antialiasing):灰阶(grayscale)渲染、亚像素(sub-pixel)渲染。

  渲染方法

  灰阶渲染是一种通过控制字体轮廓上像素点的亮度达到字体原始形状的方法。

  亚像素渲染利用了LCD屏(液晶屏)中每个像素是由R、G、B三个亚像素的颜色和亮度混合而成一个完整像素的颜色这一原理,将字体轮廓上的像素点由三个亚像素体现以达到原始形状的方法。与灰阶渲染相比,分辨率在垂直方向放大了三倍,因此渲染效果更好,但是所耗内存也更多。因此在手机屏上,为了减少CPU开销,并未采用该字体渲染方法,而是采用的grayscale渲染。

  操作系统中的渲染API

  操作系统OS提供了支持不同的字体渲染方法的API。在windows下是GDI(Graphics Device Interface)和DirectWrite,OS X下是Quartz。

  GDI分为GDI Grayscale和GDI ClearType。前者为灰阶渲染API,后者是亚像素渲染API。由于GDI ClearType并未对字体进行垂直方向的平滑,因此当字体较大时会出现边缘不平滑的情况。为了弥补GDI ClearType的不足,MS实现了DirectWrite API,它在GDI ClearType的基础上增加了垂直方向的平滑。

  但是!字体渲染的API都是由浏览器厂商自己选择的!

  使用同一颜色,感官上的颜色深浅为:黑白渲染>grayscale>sub-pixel。

  Chrome35/36采用的是GDI ClearType,因此在字体较大时边缘会出现毛刺,而FF30采用的DirectWrite则没有此类问题。如下图所示:


  根据以上两图可以发现,Chrome的字体渲染效果没有Firefox的好。为缩小Chrome与FF/IE的差异,一种方法是使用-webkit-text-stroke:0.5px;如果使用1px的话就有点粗了。

  虽然该hack使Chrome下字体的边缘有所光滑,但字体在webkit内核浏览器中看上去“模糊”了。

  常用字体在浏览器中的渲染情况


  从使用Microsoft Yahei, Tahoma和Arial字体可以看出,在Chrome35中,由于转换成GDI Grayscale渲染,49px的字比48px的边缘光滑很多。字体较大时,GDI Grayscale比GDI ClearType具有更好的渲染效果。

  在实际中会遇到在如Tahoma/Arial字体下17px和18px的“字重”有明显差别。这个现象涉及到字体设计,简单地说就是在浏览器渲染字体之前,字体本身会调整字型和笔画所占像素。想了解更多细节,请参考a closer look at TrueType hinting。

  启动Chrome中的DirectWrite

  在chrome://flags下启用实验性DirectWrite字体渲染系统:#enable-direct-write会使48px以下的字体均为sub-pixel渲染。仅适用于测试环境!(需重启Chrome)


  Chrome37 beta将该特性移除实验特性,并将在Chrome37中实现在windows下使用DirectWrite API对字体渲染,相信在Chrome37中以上提到的浏览器字体渲染差异会得到解决。

  字体格式在不同浏览器下的渲染


  font-smoothing: subpixel-antialiased | antialiased;

对应为sub-pixel和grayscale。
已废止!

font-weight: bold;
Chrome35, IE7/8:与normal字体渲染一致(包括数字和字母);
IE9+/FF30:grayscale,部分简单中文字体保持原有渲染。

font-style:italic;
Chrome35, IE7/8:与normal字体渲染保持一致;
IE9+/FF30:sub-pixel渲染。

opacity: 属性值<1
Chrome35:sub-pixel渲染的字体“降级”为grayscale渲染;
IE9+/FF30:保持不变

transform 2D

transform: rotate(n);
n=90*k deg(k=整数), 保持未旋转的字体渲染;
others,sub-pixel渲染。Chrome35在48px+为grayscale渲染。
transform: scale(x,y); 与字体大小m有关。以simsun为例,具体如下:

Chrome35:
x*y*m<12, Chrome35 sub-pixel渲染;
12<x*y*m<=48*48=2304 sub-pixel渲染; x*y*m>2304 grayscale渲染,12px-24px存在一定范围的黑白渲染(tahoma是12px-16px)。

FF30、IE9+:
m*m*n<=99*99=9801 sub-pixel渲染; m*m*n>9801 grayscale渲染。

transform: skew(n);
n=90*k deg(k为整数), 保持未倾斜的字体渲染;
others, sub-pixel渲染。Chrome35在49px+为grayscale渲染,IE9+, FF30在100px+为grayscale渲染。

transform 2D & transition

运动中:以12px为例: 在Chrome35和FF30下,运动中的字体均是grayscale渲染;
运动结束:Chrome35, FF30, IE9+均为sub-pixel渲染。
从运动开始到运动结束产生了两次渲染变化(sub-pixel到grayscale,grayscale到sub-pixel)会出现“闪现”的现象。


  Transform 3D

  当元素进入GPU中渲染时,在Chrome35+中的字体为grayscale渲染,IE11和FF30保持sub-pixel渲染不变。若transform值函数(如translate3d(), scale(), rotate()等)中的参数为非整数,会导致字体模糊。在使用iScroll模拟滚动的项目中会出现字体模糊。以下是对该问题的一个还原:

  -webkit-transform: translate3d(1.5px, 1.5px,0);


  -webkit-transform: translate3d(1px, 1px,0);


  Chrome 36中使用transform不需要-webkit-前缀了!

  为了防止以上模糊情况的出现,可以通过JS中的Math.round()/Math.ceil()/Math.floor()等函数使其为整数。

  当加入perspective()值时,Firefox30渲染又有所不同。

  transform: perspective(1px) translate3d(1.5px, 1.5px,0);在FF30中作用的元素为grayscale渲染。


  transform: perspective(1px) translate3d(1px, 1px,0); 在FF30中作用的元素为sub-pixel渲染


  E11均为sub-pixel渲染。

  此情况下运用opacity<1的声明,IE10+为grayscale。


  Chrome transform: perspective()对文档后面元素的影响

  Chrome35+,当transform中声明有perspective()时,若文档后面声明transform的元素进入该声明作用的元素的layer-borders的区域时,仍然会受到该声明的影响。声明作用元素的溢出部分同样会对后面元素造成影响。合成渲染层内部文字进入GPU渲染。


  启动Show composited layer borders,在Chrome中测试的结果截图为:


  总结

  字体渲染与操作系统、浏览器、字体格式以及CSS属性有关。本文重点罗列了一些在Windows Chrome中字体渲染与FF/IE的差异和对应缓解/解决问题的方案。Chrome在字体渲染上目前落后于IE/FF,但之前官方博客称Chrome 37将实现在windows下使用DirectWrite API,Chrome在字体渲染方面将赶上IE/FF等浏览器,以上的差异性也将减小甚至消失。

时间: 2024-09-23 03:56:11

浏览器字体渲染的秘密的相关文章

网页字体全知道:网站字体渲染过程

文章描述:我们知道同一种字体在不同浏览器上的表现有可能是不同的,除了浏览器,还有哪些导致表现不同的因素呢?不同系统下字形的渲染也是不一样的,根本原因是什么呢?我们希望各浏览器下字体排版一致,实现的话有完美的方案吗? 前言 我们知道同一种字体在不同浏览器上的表现有可能是不同的,除了浏览器,还有哪些导致表现不同的因素呢?不同系统下字形的渲染也是不一样的,根本原因是什么呢?我们希望各浏览器下字体排版一致,实现的话有完美的方案吗? 带着这些问题我们来看看字体渲染的过程: 解码 了解解码之前,我们稍微先简

网站字体渲染过程

前言 我们知道同一种字体在不同浏览器上的表现有可能是不同的,除了浏览器,还有哪些导致表现不同的因素呢?不同系统下字形的渲染也是不一样的,根本原因是什么呢?我们希望各浏览器下字体排版一致,实现的话有完美的方案吗? 带着这些问题我们来看看字体渲染的过程: 解码 了解解码之前,我们稍微先简单回顾下编码的一些知识,常见的名词有:ASCII .GB2312.Big5.Unicode.UTF-8,它们之前有什么区别或联系呢?简单来说,起初美国国家标准协会ANSI制定了一个标准,规定了常用字符的集合以及每个字

Windows 7中的字体渲染

显示方面,在Vista的基础上,微软对Windows 7进行了多方面的改进,包括全新的任务栏.一些新的UI元素.新的驱动模型WDDM1.1等等.当然,也包括字体. ClearType ClearType是微软在Vista中引入的字体渲染方式.由于用户80%的时间几乎都要花在阅读上,微软特别看重用户在字体方面的体验,而ClearType得出现正是为了通过特殊的渲染方式给予LCD和CRT显示器以出色的显示效果的. PS:在Vista下,经常有人会问,字体发虚怎么办?其实只要右键 - 个性化 - 颜色

QQ浏览器高速渲染组件怎么开启

QQ浏览器高速渲染组件怎么开启         一.安装与启用 选择 菜单-QQ浏览器设置-扩展工具,右上方的菜单.设置.应用管理里面第一个插件,就是高速渲染组件 安装完成后会自动启用 二.停用与卸载 对于安装后不想使用该组件的用户,可以选择停用或者卸载该组件,停用或卸载时会重新加载已用该组件打开的网页:  

win8系统360浏览器字体怎么调

  win8系统360浏览器字体怎么调          方法一: 1.在浏览器按住键盘左下角的"Ctrl"不放,然后按下"+"或"-" 来放大或者缩小,在按住"Ctrl"键的同时也可以使用鼠标滚轮来放大缩小. 方法二: 1.在浏览器的右下角我们可以看到100%的缩放页面比例按钮,点击该按钮; 2.通过移动滑块即可调整网页窗口大小! 方法一属于通用方法,在其他浏览器中也可以使用. windows8教程 windows10教程

win8系统360浏览器字体过大或过小怎么调整

  win8系统360浏览器字体过大或过小怎么调整                    方法一: 1.在浏览器按住键盘左下角的"Ctrl"不放,然后按下"+"或"-" 来放大或者缩小,在按住"Ctrl"键的同时也可以使用鼠标滚轮来放大缩小. 方法二: 1.在浏览器的右下角我们可以看到100%的缩放页面比例按钮,点击该按钮; 2.通过移动滑块即可调整网页窗口大小! 方法一属于通用方法,在其他浏览器中也可以使用.

win10预览版10041无斯巴达浏览器 IE浏览器Edge渲染引擎更新

  3月19日消息,微软在官方IE博客中不仅确认了斯巴达浏览器预览版将包含在下个Win10版本中,而且还列出了本次Build 10041版本中IE浏览器Edge渲染引擎更新的细节.本次更新的引擎功能是斯巴达浏览器的一部分,感兴趣的用户可以暂时用IE浏览器实验功能来"抢先"体验. 本次更新的渲染引擎内容比较丰富,主要包括以下几个方面: • 提升ECMAScript 6兼容性(在当前Win10预览版的Kangax ES6兼容性测试中提高74%) • 扩展支持DOM L3 XPath • 支

XP系统下浏览器字体怎么变小了

  XP系统下浏览器字体怎么变小了          方案一: 1.在浏览器的右上方点击工具选择Internet选项; 2.在选项里点击辅助功能; 3.在辅助功能里在不使用网页中指定的字体大小一栏中打勾,点击确定; 4.就这样,字体就比刚才的字体来得大了; 5.也可以点击选项里的字体,选择网页字体,点击确定,这样的字体看起来更舒服点,眼睛也不会不舒服了; 6.看下前后的效果对比哈. 方案二: 1.在浏览器的右上方选择查看,点击网页缩放,选择比原来大点; 2.又或者在浏览器的右下方找到100%,点

Win8.1系统英文字体渲染不正常的解决办法

  小编为大家整理了一下关于Win8.1系统英文字体渲染不正常的解决办法. 目前解决方法只能替换回Win8的字体,方法如下: 1.下载Win8的宋体:Win8字体下载 2.打开字体文件点击安装 3.倒入注册表文件:注册表文件下载 4.重启电脑