第二十六天:使用相對字型尺寸

網站的重點就是文字,幾乎沒什麼例外。新聞、輿論、想法、理念、故事、創新的文學作品、電子商務:全都是文字。視覺設計跟圖像當然很重要,但是如果人們連妳的文字都讀不到,那有什麼用呢?

2000 年秋天時,Jeffrey Zeldman 發表了一篇著名的文章,指出使用相對字型尺寸是不可能的,這是因為瀏覽器都有一大堆的錯誤,包括 Netscape 4 以及之後的眾多瀏覽器也是如此。雖然 Netscape 4 仍然沒有修正錯誤,而且也繼續在被使用,但是至少我們都從中學到一些實作相對字型尺寸的方法( Zeldman 也是。他最近重新設計的 Web Standards Project 網站也使用下面描述的技術)。

我們在能支援的瀏覽器裡使用相對字型尺寸,而在不支援的 Netscape 4 裡使用絕對字型尺寸。即使不使用多個樣式表也能完成這項任務。 我馬上就會提供一個可以直接複製/貼上的解決方案,讓妳套用在 Movable Type 預設模版跟 Radio 的所有預設主題上。接著也會對技術本身作些囉唆的解釋,好讓妳能夠在其他模版上採行。

誰因此獲益?

  1. Lillian 從中獲益了。因為 Lillian 上了年紀,眼睛沒辦法看清楚網頁。就像其他 80% 的網際網路人口一樣,她使用的是 Windows 上的 Internet Explorer 。除非網站設計師明確地指定相對字型尺寸,否則這將沒辦法支援相對字型。 Lillian 雖然有修改過瀏覽器的預設字型尺寸(在「檢視」選單下的「字型」選項裡),但它在使用絕對字型尺寸的網站上表現並不好。這些網站包括所有現有的網誌模版。例如對 Lillian 來說,Movable Type 的預設模版看起來就像這樣:

  2. 透過 Lillian 的眼睛所看到的 Movable Type 預設模版:文字都模糊地沒辦法讀

    假使這個模版使用的是相對字型尺寸,對大部分不需要修改字型尺寸的人來說,看起來是完全相同的。但是在 Lillian 眼中會是這樣:

    透過 Lillian 的眼睛所看到的 Movable Type 預設模版:文字仍然模糊,但大到足以閱讀

    我再強調一次:如果人們連妳的文字都讀不到,那有什麼用呢?

怎麼做: Radio

找出妳 Home Page Template 裡的 <style> 部分,最頂端的 CSS 規則看起來應該像這樣:

body, td, th, p {
  font-family: verdana, sans-serif;
  font-size: 12px;
}

保持原狀,但是在後面接上這些東西:

/*/*/a{}
body,
body td,
body th,
body p {
  font-size: x-small;
  voice-family: "\"}\"";
  voice-family: inherit;
  font-size: small;
}
html>body,
html>body td,
html>body th
html>body p {
  font-size: small;
}  
/* */

請確定妳有在開頭跟結尾的地方都加上那些註解,它們是一切的關鍵。後面將會加以說明。

怎麼做: Movable Type

Movable Type 的預設模版比 Radio 要複雜,不過我們做的事情還是一樣,只不過這次份量又多了點。請在樣式表模版 (styles-site.css) 結尾處加上這些東西:

/*/*/a{}
body,
body a,
body .calendar,
body .calendarhead,
body .title,
body .sidetitle,
body .syndicate,
body .powered,
body .comments-post,
body .posted {
  font-size: xx-small;
  voice-family: "\"}\"";
  voice-family: inherit;
  font-size: x-small;
}
html>body,
html>body a,
html>body .calendar,
html>body .calendarhead,
html>body .title,
html>body .sidetitle,
html>body .syndicate,
html>body .powered,
html>body .comments-post,
html>body .posted {
  font-size: x-small;
}

body .date {
  font-size: x-small;
  voice-family: "\"}\"";
  voice-family: inherit;
  font-size: small;
}
html>body .date {
  font-size: small;
}

body #banner {
  font-size: 200%;
}

body .description {
  font-size: 60%;
}

body .blogbody {
  font-size: 110%;
}

body .blogbody,
body .calendar,
body .calendarhead,
body .side,
body .title,
body .sidetitle,
body .syndicate,
body .powered,
body .comments-body {
  line-height: 128%;
}
/* */

也請確定妳有在開頭跟結尾的地方都加上那些註解了。

怎麼做:深入探討

基本概念是使用字型尺寸關鍵字。它們(因為舊版瀏覽器的錯誤而)很少被用到,但其實它們有三個有趣的特性:

  1. 它們不會加成 (compound)。如果妳在「 main 」段落裡使用了 90% 的字型尺寸,又在其中的「 post 」段落使用 90% 的字型尺寸,有些瀏覽器會用 81% (90% x 90%) 來顯示「 post 」,但有些會用 90% 來顯示。隨著一層層的巢狀套用(在使用表格製作版面時很常見),文字馬上就會隨著百分比的加成而縮小到看不見。然而如果妳的「 main 」段落使用了 small 的字型尺寸,又在其中的「 post 」段落使用 small 的字型尺寸時,所有的瀏覽器都會用 small 的字型尺寸來顯示「 post 」。
  2. 它們改變字型尺寸的特性可以在 Windows 的 Internet Explorer 下正確顯示。這點蠻神奇的,因為 small 聽起來就像是個絕對字型尺寸(尤其是加上前面關於巢狀的說明後),但是我發誓它真的可以運作。
  3. 它們永遠不會小。 Lillian 在 Internet Explorer 裡使用的「字型」設定可以自由修改尺寸。許多視力正常的人比較希望看到比正常字型來得小一點的字。使用百分比設定的字型尺寸當與預設的最小字型尺寸合成之後,就會變得模糊不清。但使用字型尺寸關鍵字總是可以至少維持在 9px,這在任何字體下都可以閱讀(假設妳的視力不錯)。

所以我們使用字型尺寸關鍵字來設定我們的基礎大小。如果需要控制得更加精細的話,我們還可以使用百分比,但只能用在末端的文字上(像是可以用在「 post 」,但不能用在「 main 」),以避免百分比的加成及過小的問題。

以下是使用字型尺寸關鍵字的基本概念:

p {
  font-size: 12px;
}

/*/*/a{}
body p {
  font-size: x-small;
  voice-family: "\"}\"";
  voice-family: inherit;
  font-size: small;
}
html>body p {
  font-size: small;
}
/* */

接下來的都很重要,所以請注意。

  1. 首先,我們定義 <p> 的絕對尺寸 (12px) 。包括 Netscape 4 在內,所有的瀏覽器都會接受這個樣式設定。
  2. 接著我們加入「 /*/*/ 」這個古怪的註解。根據 Netscape 4 的錯誤,所有在這個註解之後的東西都會被忽略掉。如此一來,只有 Netscape 4 以外的瀏覽器才會看到之後的樣式。
  3. 緊接在那個古怪的註解之後,我們又加入一個空白的樣式「 a {} 」。 Mac 上充滿錯誤的 Opera 5 會忽略這個樣式(只有這一個),而接受其他所有的。
  4. 現在我們已經切出一個範圍了,在這個範圍內所定義的規則祇會套用在 Netscape 4 以外的其他瀏覽器上。接下來我們就可以開始定義相對字體尺寸(這也就是 Netscape 4 所無法處理的)了。首先我們要用「 body p 」選擇子來重新定義 p 標籤的作用。因為 CSS 可行的關係,這將會覆寫掉先前的 p 選擇子(用技術名詞來描述的話,就是「 body p 」選擇子比「 p 」選擇子還要更具特定性)。
  5. 我們把所有 <p> 標籤的字體尺寸重新定義成 x-small 。這個字體尺寸關鍵字在預設的情況下,會被 Windows 上的 Internet Explorer 5 轉譯成 12px 。然而祇要使用者(從檢視選單)更改了「字型」,這些文字就可能會依照使用者的設定而變得更大或更小。這也正是我們的目的(請注意:我們現在已經對 IE5/Win 定義了兩次字體尺寸;不過這並沒有關係,因為更特定的選擇子總是會勝出,而讓前一個選擇子被忽略掉)。
  6. 很不幸地 IE5/Win 在字體尺寸關鍵字上有一刻度的錯誤:世界上所有其他瀏覽器(包括 IE5/Mac 、 Netscape 6 、 Mozilla 、 IE6/Win)都會把 x-small 轉譯成 10px ,而非 12px 。不過很幸運地, IE5/Win 另外還有一個分析錯誤之處,可以被我們拿來加以利用:當他看到那個看起來很奇怪的 voice-family 時,會誤以為整個「 body p 」選擇子已經結束了,然後就忽略掉「 } 」之後的那幾列。
  7. 現在我們又切出了一個更小的範圍了,在這個範圍內所定義的規則祇會套用在 IE5/Win 以外(至於 Netscape 4 早就被排除在外了)的瀏覽器上。如此一來我們就可以再把字體尺寸重新定義成 small 了。這麼一來,在非 IE5/Win (也就是會一路解讀到這一層的那些)瀏覽器上就會被正確地解讀成 12px 了(在預設的情況下)。當然,如果使用者把「字體尺寸」設成較大,這裡的文字也會變得比較大。這仍舊是我們所想要有的功能。
  8. 但是等一下! Opera 5 也有跟 IE5/Win 一樣的分析錯誤,所以有可能也會被 voice-family 黑克手法弄混,可是他又會正確地轉譯字體尺寸關鍵字,結果就是我們的文字在 Opera 5 底下將會變得太小。很幸運地, Opera 5 還支援第三種選擇子:「 html>body p 」(而且這個選擇子比「 body p 」還要「更具特定性」,所以會覆寫掉前一個選擇子的內容)。 IE5/Win 並不支援這種選擇子,所以會加以忽略,而這也正是我們所需要的(因為我們已經處理過那個一刻度的錯誤了,所以現在當然不會想要再把這個偏差放回去)。 IE6/Win 同樣地也不支援這個選擇子,不過這並沒有甚麼關係,因為在「 body p 」選擇子裡,我們把「 font-size: small 」放在黑克用的「 voice-family: inherit 」之後。所有其他的瀏覽器都支援「 html>body 」選擇子;所以對他們來說,我們足足定義了次字體尺寸。這當然沒有問題,因為祇有最具特定性的選擇子纔會生效,其他的都祇會被忽略掉。
  9. 最後我們還得設定一個空註解: /* */ 。這樣纔會讓 Netscape 4 繼續分析之後的部分。任何在這個空註解之後定義的規則,也都會套用到所有的瀏覽器(包括 Netscape 4 )上。

現在讓我們反過來看:

  1. 無論使用者設定了甚麼, Netscape 4 都會把 <p> 文字顯示成 12px 。
  2. Windows 上的 Internet Explorer 5 會把 <p> 文字顯示成 x-small 。依照預設值的話,也就是 12px ;不過如果妳在檢視選單裡把「字型」設成較大的話,這裡的文字看起來也會比較大。
  3. Windows 上的 Internet Explorer 6 會因為「 body p 」選擇子裡的「 font-size: small 」的關係,而把 <p> 文字顯示成 small 。依照預設值的話,也就是 12px ;不過如果妳在檢視選單裡把「字型」設成較大的話,這裡的文字看起來也會比較大。
  4. Mac 上的 Internet Explorer 5 ,和所有平台上的 Opera 、 Netscape 6 、 Mozilla 以及(希望是啦)所有未來的瀏覽器都會因為「 html>body p 」選擇子裡的「 font-size: small 」規則,而把 <p> 文字顯示成 small 。依照預設值的話,也就是 12px ;不過如果妳用了「字體縮放」功能時,這裡的文字看起來也會比較大。

延伸閱讀

  • Mark Pilgrim: Relative Font Sizing HOWTO. 跟這裡一樣提供了所有必要的解釋;但是那一頁本身就是這個技術的範例了,所以妳可以實際看出來到底會有甚麼作用。
  • Todd Fahrner: Size Matters: Making Font Size Keywords Work.
  • Caio Chassot: Hiding CSS from Netscape 4 但不使用多重樣式表。
  • Tantek Çelik: Box Model Hack. How to hide CSS from Internet Explorer 5 for Windows.
  • The Web Standards Project 同時也用了字體尺寸關鍵字來黑克 IE5/Win ;祇不過他們使用了 Javascript 的解決方案(而不是用內嵌註解黑克法)來處理 Netscape 4 的問題。
  • Owen Briggs: Text Sizing. 這裡有許多相對字體尺寸技術在各種不同瀏覽器、平台以及預設字體設定下的畫面擷取圖片。