原則上 Unicode 中只對字,而非字形編碼。css
隨着計算機字體 (computer font) 的普及,可縮放的矢量字體的出現使得「字型」與「字體」的界限逐漸模糊,現今這兩個概念在數字排印領域愈來愈多地被當作同義詞使用。html
例如 Windows 自帶的「宋體」實爲「中易宋體」。python
名稱 | 描述 | 舉例 |
serif(襯線體) | 襯線體有爪形的襯線而且筆劃粗細有變化 | Centaur,Garamond,Caslon,Baskerville,Didot,Bodoni |
sans-serif(無襯線體) | 徹底拋棄裝飾襯線,筆畫粗細對比小,x高度較高 | Helvetica,Franklin Gothic,Futura,Gill Sans,Optima,Univers,Myriad,Avenir |
cursive(手寫體) | 通常具備連筆(joining strokes)或者其它除斜體字體外的手寫特徵 | Comic Sans MS |
fantasy(幻想體) | 主要是裝飾性的,但仍然具備字符表現(與不表現字符的Pi或者Picture字體相反) | Bodoni Ornaments |
monospace(等寬體) | 全部字形都具備相等的固定寬度 | Menlo |
這裏面,咱們常常用到的是serif
體和sans-serif
體git
Serif
強調字母筆畫的開始及結束,所以先後連續性強,易讀性高。github
Sans Serif
則較醒目,但在行文閱讀的情況下,Sans-Serif
容易形成字母辨認的困擾,常會有來回重讀及上下行錯亂的情形。在小字體的場合,一般Sans-Serif
比Serif
更清晰。web
一般文章的內文、正文使用的是易讀性較佳的 Serif
字體,這可增長易讀性,並且長時間閱讀下由於會以word爲單位來閱讀,較不容易疲倦。算法
而標題、表格內用字則採用較醒目的Sans Serif
字體,它須要顯著、醒目,但沒必要長時間盯著這些字來閱讀。chrome
像宣傳品、海報類,爲求醒目,它的短篇的段落也會採用Sans-Serif
字體。但在書籍、報刊雜誌,正文有至關篇幅的情形下,則應採用Serif
字體來減輕讀者閱讀上的負擔。在Web設計及瀏覽器設置中也應遵循此原則爲是。數據庫
中文的書寫體系有兩種標準,一種是簡體中文,一種是繁體中文windows
名稱 | 描述 | 舉例 |
宋體(明朝體、明體) | 橫筆畫水平、豎筆畫粗壯、擁有華麗但規範字腳的字體 | 中易宋體(SimSun),新宋體( the Times New Roman) |
黑體(哥特體) | 結構方正,沒有字腳 | 中易黑體(SimHei),微軟雅黑(Microsoft YaHei),思源黑體( Source Han Sans) |
楷體 | 橫筆畫也能夠帶角度,柔軟且富有彈性的末端,以及符合天然的筆觸寬度 | Kaiti,方正楷體 |
仿宋(宋朝體) | 橫微微傾斜,不會有很大的字腳,橫豎筆畫的粗細對比也沒有宋體那麼大 | 方正仿宋 |
美術體 | 美術體是一類極具風格的字體,它們能夠包括從稚嫩到厚重到新奇的各種風格 | 丁丁手繪體 |
另外,圓體(圓黑體)一般也納入黑體。傳統上說的「等線體」以當代視角來看一般是較爲幼細的黑體。
中文字體界很多人不主張用「襯線」、「無襯線」來指代宋體和黑體。
宋體,原形爲宋代模仿楷書基本筆劃(如點、撇、捺),但因應當時以木板做活版印刷,爲順應木的自然紋理,而從楷體左低右高的斜橫演變成直橫,由於減低損耗而將豎劃加粗的印刷用字體。到明代,這種字體逐漸脫離楷書的模樣,成爲一種成熟的印刷字體。
黑體的發明比較晚,學者對於黑體的歷史有很大的爭議,但咱們能夠發現它是二十世紀早期廣告印刷品的產物。
因爲宋體是由於印刷誕生的,因此它更適合報紙和書籍的正文類文字的排版。
因爲黑體醒目的特色,經常使用於標題、導語、標誌等等。因爲漢字筆劃多,小字的黑體清晰度較差,因此一開始主要用於文章標題,但隨着制字技術的精進,已有許多適用於內文的黑體字型。
本質上是點陣圖片的集合。
渲染極快
顯示效果穩定
容易建立
在小字號、多筆畫時渲染效果較好
視覺效果較差
不適合縮放
是向量圖的集合,用 Bézier 曲線描述字形,適合縮放。
PostScript 字體
Adobe 開發
用三次 Bézier 曲線描述字形。
私有 hinting,價格昂貴
質量高,適合打印專業質量的印刷出版物
又細分爲 Type1 / Type3 / CID 等類型
TrueType 字體
Apple 爲對抗 Adobe 的 Type1 與 Microsoft 共同開發
用二次 Bézier 曲線描述字形,渲染較快
可內置點陣字體
在 OS X 和 Windows 中是最多見的字體格式
OpenType 字體
源於 Microsoft 獨自開發的 TrueType Open
後 Adobe 加入開發,增長對 PostScript 輪廓的支持
PostScript flavor / TrueType flavor
Adobe 黑體
如何理解點陣字體和輪廓字體的區別呢,其實它們的表現和圖片格式中的png8和png24的的區別很相似,點陣字體都是實色,沒有過渡色,邊緣銳利,而輪廓字體有過渡色,邊緣也比較平滑。不少人把「宋體」(Simsun)看成點陣字體,其實不是,它和「微軟雅黑」(Microsoft YaHei)同樣,都屬於輪廓字體,只不過12px~17px的宋體內置了點陣信息而已。
以下圖,前面有兩個 T 的是 TrueType 的格式字體,O 開頭的是 OpenType 的字體。
OpenType字體中的字形(glyph)、輪廓數據能夠在兩種格式中任選其一:一個是在glyf
表中TrueType格式輪廓,另外一個是在CFF
表中的CFF(壓縮字體格式,Compact Font Format)格式輪廓。CFF輪廓數據是基於PostScript語言Type 2字體格式。表格名CFF
長度爲四個字符,而且以一個空格字符結尾。
Windows、OS X、Liunx/Unix預裝中文字體demo
上面的例子列舉了Windows
、OS X
、Liunx/Unix
預裝字體以及一些版權字體
Windows | OS X | Linux/Unix |
微軟雅黑UI(MicroSoft YaHei UI)Win8+ | 蘋方-簡(PingFangSC)OS X 10.11+ | 文泉驛微米黑(WenQuanYi Microhei) |
微軟雅黑(MicroSoft YaHei )Win Vista+ | 黑體-簡(Heiti SC)Mac OS X 10.6+ | - |
中易宋體(SimSun) | 華文黑體(STHeiti) | - |
- | 冬青黑體簡體中文(Hiragino Sans GB)Mac OS X 10.6+ 非默認 | - |
Android | IOS |
思源黑體(Noto Sans CJK SC)Android 5.0+ | 蘋方-簡(PingFangSC)IOS9.0+ |
Droid Sans Fallback | 黑體-簡(Heiti SC) iPhone OS 3.0+ |
- | 華文黑體(STHeiti) |
無襯線 | 襯線 | 等寬 |
San Francisco(OS X 10.11+/IOS9.0+) | Georgia | Menlo |
Helvetica(IOS1.0+) / Helvetica Neue(OS X10.10+/IOS 4.0+) | Times New Roman | Courier |
Lucida Grande(OS X) | - | Monaco |
Segoe UI(Win Vista+) | - | - |
Tahoma | - | - |
Verdana | - | - |
Arial | - | - |
Roboto(Android 4.0+) | - | - |
Droid Sans(Android) | - | - |
爲何須要編碼?
咱們知道計算機處理的數據實際上都是二級制的數據,也就是計算機實際上只識別0和1兩種狀態。發明計算機的過程當中人們須要解決的第一個問題就是文字的處理問題,也就是咱們如何將文字符號轉化爲二級制數據,同時咱們也須要可以將轉化後的二進制數據從新轉化爲文字符號供咱們閱讀。前面的過程咱們稱之爲編碼,後面的這個過程咱們稱之爲解碼。這和電信領域更著名的一套編解碼規則莫爾斯碼是一個原理。
鑑於各個國家都有本身的字符集和編碼方式,爲了實如今一份文檔中能夠正確顯示全部類型的字符,Unicode誕生了,伴隨着互聯網的發展,Unicode字符集和UTF-8編碼方式成了互聯網通訊的標準。
這張 Unicode表分紅了不少的 block,把某一類字符放在指定的 block 中,以下圖
西文字體好比 Helvetica 等,必定會完成拉丁文對應的 block 中的字形,可是他們是不會去作 CJK(中日韓) 的字形。而特殊字符,好比表情符號等,也是有預留位置的,這也是爲啥咱們常常發現別人發過來的一些東西是方塊,由於對方發送的字符在咱們本身的機器上並無相應的字體來顯示。
詳細編碼知識請看 亂碼是怎樣造成的?
當瀏覽器收到來自Web服務器的數據後,第一步就是要把它解碼成能夠閱讀的文本,而瀏覽器判斷代碼主要是依據如下方法:
Web服務器返回的HTTP頭中的Content-Type:text/html;charset=
信息,這通常有最高的優先級;
網頁自己meta
header中的Content-Type
信息的charset
部分,對於HTTP頭未指定編碼或者本地文件,通常是這麼判斷;
假如前兩條都沒有找到,瀏覽器菜單裏通常容許用戶強制指定編碼。
部分瀏覽器 (好比 Firefox) 能夠選擇編碼自動檢測功能,使用基於統計的方法判斷未定編碼。
編碼肯定後,網頁就被解碼成了Unicode字符流,由於咱們獲得的文本多是不少種語言混雜的,裏面可能有中文、有英文,它們可能要用不一樣的字體顯示;
爲了統一處理這些複雜的狀況,咱們要將文本分爲由不一樣語言組成的小段,在有的文本佈局引擎裏,這個步驟稱爲「itemize」。分解後的文本段常被稱做「text run」,可是具體劃分的規則可能根據不一樣的引擎有所區別。
很多瀏覽器還會在這個劃分下面,在肯定具體使用的字體以後,根據使用字體的不一樣劃分更細的 run,這種 run 可能稱做「SimpleTextRun」,每一個都會使用和相鄰不一樣的字體,最後把它們逐一交給 shaper 進行排版獲得要繪製的字形,這樣一來,shaper 的工做就被簡化爲在肯定的語言、肯定的字體下排版肯定的文本,生成對應的字形和它們應該放置的位置、佔用的空間。
UA 建立(或訪問)一個 CSS 2.2 相關屬性的字體數據庫;
對每一個元素的每一個字符,先嚐試匹配第一個 font-family
名字;
找到則嘗試匹配剩餘屬性 (font-style
, font-variant
, …);
若是 (1) 沒有徹底匹配的字體,或 (2) 字體匹配但相應字形缺失,則嘗試匹配下一個 font-family
;
若是 font-family
沒法匹配,UA 分配默認字體;
若是該字符在 UA 選擇的全部字體下均無字形,UA 應選擇某個字體中的「missing character」的字形,
例如「�」。
算法包括font-stretch匹配。
肯定了font-style匹配中全部可能的狀況。
小型大寫字母字體不做爲字體匹配過程的一部分進行匹配,它們如今經過字體特性進行處理。
須要Unicode variation selector匹配。
小米官網
font: 14px/1.5 "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei", "Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei", sans-serif;
name - Naming Table
按 OpenType 規範,字體的名稱信息存在 name 表中。
Name Records
Platform ID
Platform-specific encoding ID
Language ID
Name ID
…
ID | 含義 |
1 | Font Family name (Family) |
2 | Font Subfamily name (Style) |
4 | Full font name (Full) |
6 | PostScript name |
16 | Preferred Family |
17 | Preferred Subfamily |
18 | Compatible Full (OS X only) |
21 | WWS Family Name |
22 | WWS Subfamily Name |
Name Type | Chinese - PRC | English - United States |
Family | 宋體 | SimSun |
Style | Regular | Regular |
Full | 宋體 | SimSun |
PostScript name | 宋體 | SimSun |
Name Type | Chinese - PRC | English - United States |
Family | Adobe 黑體 Std R | Adobe Heiti Std R |
Style | Regular | Regular |
Full | - | AdobeHeitiStd-Regular |
Preferred Family | Adobe 黑體 Std | Adobe Heiti Std |
Preferred Subfamily | R | R |
PostScript name | AdobeHeitiStd-Regular | AdobeHeitiStd-Regular |
Windows 的字體預覽會採用你目前的系統語言對應的 Preferred Family 做爲命名,若是此項缺失則會用系統語言 Family、英語 Preferred Family、英語 Family。
對瀏覽器來講不一樣瀏覽器的處理策略是不同的,好比 IE9 和 FF4 支持按照 Preferred Family 選字而 Chrome 只按照 Family(Opentype 規範裏的 [name] 表項目)搜索。
fallback是字體匹配算法的重要機制,咱們看一下下面的例子:
font-family: 'Helvetica Neue', 'Helvetica', 'Microsoft Yahei', sans-serif;
這個 fallback 的規則能夠總結爲
(hasFont && isInUnicodeTable) ? 'Current Font' : 'Next Font'
就這樣一直找匹配的字體,直到系統默認,因此通常都把系統默認的5類字體放到 font-family 定義的最後來寫。
CSS規範裏只簡單的說執行「system font fallback」。但這個過程在不一樣的系統不一樣的瀏覽器下可能很不同,好比:
OS相關機制
Linux下通常經過fontconfig去根據語言、風格等參數來選擇fallback,但不一樣瀏覽器的實現還可能有區別。
Windows下則通常會使用系統的Font Linking機制,根據註冊表內的FontSubstitutes信息來尋找。
OS X是按照字體後備列表進行fallback。
瀏覽器配置
WebKit settings 中可設定各個 generic family 的默認值。
Firefox訪問 about:config 後篩選出的 font 相關項中包含不一樣語言下 generic families 的默認值。
Webkit會使用font-family
列表的第一個字體和這段文字所屬的語言來尋找fallback字體,像Times
這樣的serif字體對應的中文fallback字體,在Mac OS X下是華文宋體(STSong)。
Firefox則會根據sans-serif
這樣的通用font-family
和對應的語言匹配到設置中針對對應語言的默認字體,好比在MAC OS X 默認的中文非襯線字體是華文黑體(STHeiti)(新版本 OS X是蘋方-簡)。
charset、lang 屬性、font-family值
由於在這裏不一樣的瀏覽器可能有不一樣的行爲,因此建議在CSS中應寫明對應平臺所使用的字體。
具體的字體選擇還有一些不太容易注意的細節,也是各個瀏覽器差別比較大的一點,可能會出現這樣一些問題:
是否支持用字體的PostScript name選擇:如STHeiti
的Light版本又稱做STXihei
,或者是否能用full name 選擇:有的瀏覽器不能正確地將CSS裏對字體的font-weight
或者font-style
等要求映射到特定的字體上,尤爲是在字體使用了非標準的style明明的狀況下。
是否支持按 Localized name選擇:好比能不能用「宋體」來表明「Simsun」。以Mac OS X下的瀏覽器爲例,Firefox支持這樣的寫法,但基於Webkit的瀏覽器通常不支持,這樣的問題CSS規範沒有限定,因此不管哪一種狀況都是容許的。
總的說來,若是要保證最大限度的兼容性,在 CSS 書寫的時候應該儘量選擇明確、不容易出錯的寫法,儘可能少隱式地讓瀏覽器本身肯定 (be explict instead of implict),雖然隱式寫法一般比較簡潔,但除非你 100% 肯定想支持的瀏覽器在你想支持的平臺下都能支持這個寫法,不然仍是不該該輕易用。
其它注意事項請參看:font-family 沒有設定中文字體時,漢字應該怎麼顯示?
當字體肯定之後,就能夠將文本,字體等等參數一塊兒交給具體的排版引擎,生成字形和位置,而後根據不一樣的平臺調用不一樣的字體rasertizer
將自行轉換成最後顯示在屏幕上的圖案,通常瀏覽器都會選擇平臺原生的resterizer
。
不一樣瀏覽器有着不一樣的渲染引擎。Mac OS X 用戶使用 CoreText 渲染引擎,Windows7 和 Windows Vista 用戶使用 DirectWrite.aspx) 或 GDI ,而 Windows XP 則使用 GDI。
GDI 分爲 GDI Grayscale 和 GDI ClearType 。前者爲灰階渲染 API,後者是亞像素渲染 API。因爲 GDI ClearType 並未對字體進行垂直方向的平滑,所以當字體較大時會出現邊緣不平滑的狀況。爲了彌補 GDI ClearType 的不足,MS實現了 DirectWrite API,它在 GDI ClearType 的基礎上增長了垂直方向的平滑。
對比圖片來看看它們之間的區別,其中上圖爲FacitWeb字體,下圖爲 Minion Pro字體。
使用同一顏色,感官上的顏色深淺爲:黑白渲染> grayscale > sub-pixel。
iOS 和 Mac 的渲染引擎同樣,但採用的是灰度渲染,默認狀況下亞像素抗鋸齒是關閉的,但能夠通知設置開啓。
因爲渲染策略的不一樣,字母a在不一樣的瀏覽器和 OS 下的渲染表現也不一樣。第一個是理想模型的a,第二個是灰階渲染的a,第三個是亞像素渲染,第四個是黑白渲染。
注:從 chrome52 開始,google 中止對於老的操做系統的支持,包括 windows xp 和 windows vist a中止了 GDI 的字體渲染,從而只支持 DirectWrite。
當肯定了編碼、字體類型、排版引擎、瀏覽器後,就要進行光柵化了,光柵化是將文字從一個向量表示(好比一個TrueType)轉化到光柵或者位圖表示的過程。在這個過程當中每每涉及到一些抗鋸齒技術使得屏幕上的字體更加順滑易讀,這也常常會涉及到「字體微調(font hinting)」技術。
根據以上總結咱們能夠看出,不一樣系統預裝的字體不一樣,不一樣瀏覽器的默認字體也不一樣,並且還有渲染引擎的差別。因此,要想達到比較好的顯示效果,須要設置好font-family
。
首先肯定要選擇字體的元素應該使用的字體風格,好比是襯線字體、非襯線字體仍是 cursive
、fantasy
之類的。
優先聲明英文字體,好比 Mac OS X 下有 Helvetica
也有 Arial
,但 Helvetica
(可能) 效果更好,Windows 下則通常只有 Arial
,那麼寫 Helvetica
, Arial
就比 Arial
, Helvetica
或者只有 Arial
更好。
絕大部分中文字體都包含英文字母和數字,可是大多數中文字體中的英文和數字部分都不是特別漂亮,因此建議對英文字體先進行聲明。
而後列出中文字體,Windows下,Microsoft Yahei
是最經常使用的字體,Mac若是安裝了Office,系統也會安裝Microsoft Yahei
字體,可Mac下Microsoft Yahei
顯示效果不是太好,因此通常把Mac的字體放在前面,Microsoft Yahei
放在後面,最後還能夠跟上Linux下的WenQuanYi Micro Hei
。
最後還應該放上對應的generic family
,好比sans-serif
或者serif
。
儘可能用字體的基本名稱 (好比 English locale 下顯示的),而不要用本地化過的名稱。除非特殊狀況 (Windows 下「某些」瀏覽器在特定編碼下只能支持本地化的字體名稱)。Mac OS X 下字體名稱能夠用 Font Book
查到 (菜單 Preview -> Show Font Info),Windows 下字體信息在微軟的網站能夠獲得,Linux/X11 下可使用 fc-list
命令查到。
字體名稱中包含空格時記得用引號擴起來,好比"WenQuanYi Micro Hei"
。
文檔開頭最好指明語言,好比<html lang="en-us">。可是對於簡體中文來講,咱們不該該使用lang=zh-cn
,可是爲了瀏覽器的兼容性,還繼續使用。詳細參見網頁頭部的聲明應該是用 lang="zh" 仍是 lang="zh-cn"?。
基於以上考慮,咱們先來看看最安全的的font-family
是什麼樣的:
html lang=zh-CN//爲了兼容性,暫時先這麼寫 charset=utf-8 font-family:arial,sans-serif;
擴充一下,加上經常使用的字體fallback:
font-family: -apple-system,BlinkMacSystemFont,"San Francisco","Helvetica Neue",Helvetica,Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Microhei",sans-serif;
font-family: "\5FAE\8F6F\96C5\9ED1", Helvetica;//手機騰訊 font-family:'STHeiti','Microsoft YaHei',Helvetica,Arial,sans-serif;//手機網易
-apple-system
用於調用系統默認UI字體,而且會根據font-weight
聲明選擇恰當的變體。system
未來有可能成爲標準,-apple
爲過渡階段的廠商前綴。
BlinkMacSystemFont
:爲 macOS Chrome 應用系統 UI 字體,與上面等同。
通常移動端不須要設置中文字體,\5FAE\8F6F\96C5\9ED1
是微軟雅黑的Unicode碼,中文測試用。
Type rendering: operating systems
Using UI System Fonts In Web Design: A Quick Practical Guide
Using the System Font in Web Content