8.14.2012

試試 CSS3 Web Font

如果只是想要好看的英文字型,Google Web Font 提供非常方便的服務:
  • 能選擇多組字型
  • 能預覽這些字型在不同樣式、位置的搭配效果
  • 字型是公開授權過的
  • 不用擔心 @font-face 的多平台多字型問題
可惜沒有提供中文、日文字型,畢竟這些字型的檔案都太大(2MB+)。

TO HOST FONT


把字型檔案擺在正確的位置,並多加一行 @font-face 在 CSS 前面,就能讓 font-family 使用自已放在 server 上的字體:

<style type="text/css">
        @font-face {
                font-family: 'mikachan';
                src: url('/fonts/mikachan.otf');
        }
        /* some elsewhere ... */
        body {
                font-family: 'mikachan', sans-serif;
        }
</style>

在最簡單的情況下,用 Chrome 與 Firefox 能正常下載和顯示這字型。若字型要讓
  • 老版本的 Internet Explorer 使用 (eot)
  • 其它平台的瀏覽器使用 (svg, ttf)
  • 讓它遵循規範
那麼 @font-face 這邊就必須加上多種格式:

<style type="text/css">
        @font-face {
                font-family: 'mikachan';
                src:    url('/fonts/mikachan.eot');
                src:    url('/fonts/mikachan.eot?#iefix') format('embedded-opentype'),
                        url('/fonts/mikachan.woff') format('woff'),
                        url('/fonts/mikachan.ttf') format('truetype'),
                        url('/fonts/mikachan.svg#mikachan') format('svg');
                font-weight: normal;
                font-style: normal;
        }
</style>

當中的數個 src properties 是必要的,Nice Web Type 這邊記錄和說明每一行必須存在的原因,也詳列數年來各種不同的 bullet-proof 技巧。

不同字型格式的轉換可以用 www/ttf2eot 和 www/sfnt2woff,或是直接用線上的轉換服務:
它們會同時幫你產生對應的 @font-face CSS 和 demo page。

如果要 host 的字型變多了,可以寫一個產生 CSS @font-face 的 handler:

<?php
header('Content-Type: text/css');

function fill($buffer) {
        global $font_family;
        global $file_name;
        return str_replace('{FILE_NAME}', $file_name, str_replace('{FONT_FAMILY}', $font_family, $buffer));
}
?>

<?php ob_start('fill'); ?>
@font-face {
    font-family: '{FONT_FAMILY}';
    src: url('/fonts/{FILE_NAME}.eot');
    src: url('/fonts/{FILE_NAME}.eot?#iefix') format('embedded-opentype'),
         local('☺'),
         url('/fonts/{FILE_NAME}.woff') format('woff'),
         url('/fonts/{FILE_NAME}.ttf') format('truetype'),
         url('/fonts/{FILE_NAME}.svg#{FILE_NAME}') format('svg');
    font-weight: normal;
    font-style: normal;
}
<?php ob_end_flush(); ?>

甚至判斷瀏覽器 User Agent,僅回應指定的 @font-face rule,這樣就不需特別作 IE bullet proof。

NGINX CONFIGURATION


新增或修改這幾種附檔名的 MIME Type:

types {
    application/x-font-ttf                ttf;
    application/x-font-woff               woff;
    application/vnd.ms-fontobject         eot;
}

以及 nginx.conf,

server {
    ...
    location /fonts {
        add_header  Access-Control-Allow-Origin http://mu.adios.tw;
        gzip_types  image/svg+xml application/x-font-ttf application/vnd.ms-fontobject;
    }
    ...
}

傳輸用 gzip 是讓我們的字體能小一點點(woff 是已經壓過的格式,所以不再 gzip),要注意的是那個 header,W3C 規範瀏覽器必須禮貌性遵守字型的同源政策,也就是:

  • 你在瀏覽 Host A 的網頁
  • Host A 的 @font-face src properties 指到 Host B
  • 瀏覽器向 Host B 問字型時,Host B 會先回應含有這條 header 的訊息
  • 瀏覽器將這條 header 比對 Host A,如果一樣,才會下載並使用字型

IE9: CS3111: Unknown Error


如果 Internet Explorer 9 無法顯示字型,打開開發者工具,檢查看看是不是吐這條訊息,這表示字型檔案錯誤。詳細原因我也不明暸,應該是字體內有些屬性 Windows 不懂,這發生在從 otf 轉換的 eot 字型,後來我是拿為原本設計給 windows 的 ttf 格式來轉換 eot,就正常無虞了。

顯示字型的一致性


在字型正在被下載的過程中,採用該字體的文字:
  • Chrome 不顯示任何東西,直到字體下載完,才會顯示
  • Firefox 顯示預設字型,直到字體下載完,才會更新
WebFont Loader 能彌平這種不一致性。要嘛就讓所有瀏覽器都不顯示,要嘛就是先顯示預設字型。

沒有留言: