掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流
瀏覽器是我們最常用的軟件之一,文本又是網(wǎng)頁中最主要的元素,在瀏覽器顯示文本的過程中有許多有趣的細節(jié),值得展開來講講,或許能減少一些誤解。這 是一個比較粗略的,概括性的介紹,盡可能不涉及過多的技術細節(jié)和具體實現(xiàn),而立足于給 Web 開發(fā)者和設計師提供一些正確的概念。

創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比青島網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式青島網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋青島地區(qū)。費用合理售后完善,十載實體公司更值得信賴。
下面的介紹主要根據(jù)我對 WebKit 和 Gecko (Firefox) 的印象來談,其他的瀏覽器也大致相同,如有闕漏之處歡迎指出。
當瀏覽器收到來自 Web 服務器的網(wǎng)頁數(shù)據(jù)之后,第一步是要把它解碼成可以閱讀的文本,因為歷史原因,不同區(qū)域和語言的網(wǎng)頁可能會使用不同的編碼方式,而瀏覽器判斷編碼主要是依據(jù)以下方法:
編碼確定后,網(wǎng)頁就被解碼成了 Unicode 字符流,可以進行進一步的處理,比如 HTML 解析了,不過我們這里跳過 HTML/XML 解析的細節(jié),單講得到了解析后的文本元素之后該怎么處理。
因為我們得到的文本可能是很多種語言混雜的,里面可能有中文、有英文,它們可能要用不同的字體顯示;也可能有阿拉伯文、希伯來文這種從右到左書寫的 文字;也有可能涉及印度系文字這樣涉及復雜布局規(guī)則的文字;另外,還可能有網(wǎng)頁內(nèi)自己指定的文本語言,比如 日本語 這樣的標記,使得日文漢字可以使用日文字體顯示 (因為 Han Unification 導致這些漢字和中文里的漢字使用同樣的代碼點,盡管很多寫法不同),”lang” 屬性也可以在 HTTP 頭、 或者 出現(xiàn),用于標記整個文檔的全局語言,通常這是一種好的習慣,方便瀏覽器進行字體匹配。
為了統(tǒng)一處理所有這些復雜的情況,我們要將文本分為由不同語言組成的小段,在有的文本布局引擎里,這個步驟稱為“itemize”,分解后的文本段 常被稱作“text run”,但是具體劃分的規(guī)則可能根據(jù)不同的引擎有所區(qū)別,比如 HarfBuzz 和 ICU 一般是根據(jù)要使用的不同排版類來劃分 (常稱作“shaper”),比如英語和法語可能使用同一個 shaper 排版,那么相鄰的英語和法語文本就會劃分到同一個 run 里,而希伯來文需要另一個 shaper,就劃分到它自己的 run 里,以 HarfBuzz 為例,它有這樣一些 shaper:
不少瀏覽器還會在這個劃分下面,在確定具體使用的字體之后,根據(jù)使用字體的不同劃分更細的 run,這種 run 可能稱作“SimpleTextRun”,每個都會使用和相鄰不同的字體,最后把它們逐一交給 shaper 進行排版得到要繪制的字形,這樣一來,shaper 的工作就被簡化為在確定的語言、確定的字體下排版確定的文本,生成對應的字形和它們應該放置的位置、占用的空間。下面先詳細說說確定字體的步驟。
說到字體,首先必須提到的就是 CSS 里的 font 和 font-family 等規(guī)則。比如這樣的規(guī)則:
- p { font-family: Helvetica, Arial, sans-serif; }
- strong { font-weight: bold; }
如果對于這樣一段文本:
A quick brown fox jumps over the lazy dog.
表示這個段落里優(yōu)先使用 Helvetica 這個 family 的字體,如果找不到,就找 Arial,如果還是找不到,就用瀏覽器設置的默認非襯線字體 (有的瀏覽器,比如 Safari 只給你一個設置,有的像 Firefox 則允許根據(jù)不同語言設置,這時可以根據(jù)前面分析得到的文本 run 語言信息來判斷該用哪個),這個過程非常簡單,大家都很好理解。稍微復雜一點的是“jumps”,它應該繼承父元素的 font-family,也用 Helvetica,但不用默認的 Regular,而用 Bold 版本,假如找不到 Helvetica Bold,就找 Arial Bold,否則就找瀏覽器設置的那個字體的 Bold 版本,假如都沒有呢?就要考慮用人工偽造的方式來顯示粗體了,這個且按下不談,先看對于中文常見的情況:CSS 指定的字體沒有覆蓋我們需要的文本時,該怎么做。比如還是上面的 CSS 規(guī)則,但對這樣的文本:
一只敏捷的狐貍…
這里的“一只敏捷的狐貍”該用什么字體呢?假設 CSS 里具體指定了中文字體,比如 Helvetica, STHeiti, sans-serif,那很簡單,按照英文字體一樣的規(guī)則來判斷:逐個字符嘗試當前的字體是否提供了針對該字符的字形,如果沒有則嘗試下一個,要是到了最 后都沒找到匹配的字體呢?CSS 規(guī)范里只簡單的說執(zhí)行“system font fallback”,但這個過程在不同的瀏覽器下可能很不一樣,比如 WebKit 會使用 font-family 列表里的第一個字體和這段文本所屬的語言來尋找 fallback 字體,像 Times 這樣的 serif 字體對應的中文 fallback 字體,在 Mac OS X 下是華文宋體 (STSong);而 Firefox 則會根據(jù) sans-serif 這樣的通用 font family 和對應的語言匹配到設置中針對對應語言的默認字體,比如在 Mac OS X 默認的中文非襯線字體是華文黑體 (STHeiti)。Linux 下一般通過 fontconfig 去根據(jù)語言、風格等參數(shù)來選擇 fallback,但不同瀏覽器的實現(xiàn)還可能有區(qū)別;Windows 下則一般會使用系統(tǒng)的 Font Linking 機制,根據(jù)注冊表內(nèi)的 FontSubstitutes 信息來尋找。因為在這里不同的瀏覽器可能有不同的行為,所以建議在 CSS 中寫明對應平臺該用的字體。
具體的字體選擇還有一些不太容易注意的細節(jié),也是各個瀏覽器差異比較大的一點,可能會出現(xiàn)這樣一些問題:
是否支持用字體的 PostScript name 選擇:如 STHeiti 的 Light 版本又稱作 STXihei,或者是否能用 full name 選擇:有的瀏覽器不能正確地將 CSS 里對字體的 font-weight 或者 font-style 等要求映射到特定的字體上,尤其是在字體使用了非標準的 style 命名的情況下,考慮到很多廠商有自己的字體命名規(guī)則,這其實很容易出現(xiàn),像 Helvetica Neue 的 UltraLight, Light, Regular, Medium, Bold 這些不同的 weight,是怎么對應到 CSS font-weight 的 100 到 900 數(shù)值上的?這就是特別容易出現(xiàn) bug 的地方。
是否支持按 localized name 選擇:比如能不能用 “宋體” 來代表 “SimSun”。以 Mac OS X 下的瀏覽器為例,F(xiàn)irefox 支持這樣的寫法,但基于 WebKit 的瀏覽器一般不支持,這樣的問題 CSS 規(guī)范沒有限定,所以無論哪種情況都是允許的。
總的說來,如果要保證最大限度的兼容性,在 CSS 書寫的時候應該盡可能選擇明確、不容易出錯的寫法,盡量少隱式地讓瀏覽器自己確定 (be explict instead of implict),雖然隱式寫法通常比較簡潔,但除非你 100% 確定想支持的瀏覽器在你想支持的平臺下都能支持這個寫法,否則還是不應該輕易用。
CSS3 新增的 @font-face 規(guī)則則是對于現(xiàn)有規(guī)則的擴展,提供了 web fonts 功能,但字體匹配算法的邏輯并沒有改變,詳細的算法可以看 CSS 規(guī)范里的說明。
當確定了字體以后,就可以將文本、字體等等參數(shù)一起交給具體的排版引擎,生成字形和位置,然后根據(jù)不同的平臺調(diào)用不同的字體 rasterizer 將字形轉換成最后顯示在屏幕上的圖案,一般瀏覽器都會選擇平臺原生的 rasterizer,比如 Mac OS X 下用 Core Graphics,Linux/X11 下用 FreeType,Windows 下用 GDI/DirectWrite 等等。關于這個步驟,typekit 的這篇 blog 可以作為參考。各個瀏覽器的差異主要來自使用的排版引擎可能對不同的語言支持有差異,調(diào)用 rasterizer 使用的參數(shù)可能有差異 (比如是否啟用 subpixel rendering、使用的 hinting 級別等等),但在同一個操作系統(tǒng)下的效果差別不會很大。
| 基于以上的介紹,可以嘗試提出一個在現(xiàn)有瀏覽器下,針對中文用戶的,書寫 CSS 字體選擇規(guī)則的建議,如下: |
原文鏈接:http://www.wufangbo.com/browser-render-text/

我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流