跨瀏覽器網頁設計密技
2013/4/15 下午 01:05:32 點擊: 列印此頁設計跨瀏覽器網頁,經常要在不同瀏覽器版本之間進行微調,調整的地方不一定只有 CSS 而已,有時候為了避開一些瀏覽器在特定版本下的 JavaScript 臭蟲,我們也會需要針對不同的瀏覽器版本撰寫不同的程式碼或內容,因此在本期文章中,我會介紹各瀏覽器 CSS Hack 技巧,以及 IE 條件式註解。
(1) 各瀏覽器 CSS Hack 技巧
撰寫 CSS 樣式時必須瞭解到樣式套用順序的觀念,也就是越晚定義的樣式,優先權越高!
舉個例子來說,如下 .page 這個樣式重複定義了 width 屬性,因此真正被套用的 width 屬性應該是 95% 這個值才對。
.page { width: 90%; width: 95%; margin-left: auto; margin-right: auto; }
不只單一則樣式裡的屬性可以重複定義,連整條樣式也能夠重複定義,一樣也是比較晚定義的樣式會蓋掉先前定義的樣式,如下範例 .page 這個樣式最後生效的 width 屬性會是 100% 才對。
.page { width: 90%; margin-left: auto; margin-right: auto; } .page { width: 100%; }
無論是 IE、Firefox、Safari、Opera 或 Chrome 瀏覽器,在解析一份 CSS 樣式表時多少都會有些不一樣的行為,但是都有一個共通的特性,那就是當瀏覽器無法解析其中一段 CSS 樣式或屬性時,就會自動忽略這一段的樣式,進而解析下一段樣式。所謂的 CSS Hack 技巧,講的就是找出不同瀏覽器版本之間不同的 CSS 解析規則,好讓網頁設計師所定義的 CSS 樣式可以讓該樣式在特定瀏覽器版本下無法辨識,但另一個版本的瀏覽器可以辨識的技巧,也是因為這類「小技巧」十分神奇,所以才被稱為 "Hack"。
備註:筆者倒覺得 CSS Hack 的神奇之處不是他的語法特別,而是為什麼有人可以找的到這麼多怪異 CSS 語法,國外還有些人會寫許多設法找出各種可能的 CSS Hacks,真讓人佩服。
CSS Hack 主要分成兩種類型,分別描述如下:
樣式屬性的密技 ( Attribute Hacks )
選取器的密技 ( Selector Hacks )
樣式屬性的密技 ( Attribute Hacks )
只有 IE6 才能解析的屬性,在屬性名稱之前加上一個底線 ( _ )
#style1 { _color: blue }
只有 IE6、IE7 才能解析的屬性,在屬性名稱前面加上星號 ( * ) 或井號 ( # )
#style1 { *color: blue; }
#style1 { #color: blue; }
只有 IE7、IE8、IE9 才能解析的屬性,在屬性名稱後面加上一個註解 ( /**/ )
#style1 { color/**/: blue }
只有 IE6、IE7、IE8 才能解析的屬性,在屬性值最後加上一個 \9 字串
#style1 { color: blue\9; }
只有 IE7、IE8 才能解析的屬性,在屬性名稱後面加上一個怪怪的註解 ( /*\**/ ),在屬性值最後加上一個 \9 字串
#style1 { color/*\**/: blue\9; }
只有 IE8、IE9 才能解析的屬性,在屬性值最後加上一個 \0/ 字串
#style1 {color: blue\0/;}
有了這些特殊的 CSS Hacks,網頁設計師便可以利用這些特性來設計針對特定瀏覽器的 CSS 問題來解決不同版本之前的相容性問題。舉個例子來說,如果你想針對不同的 IE 版本給與不同的顏色顯示文字,你就可以將 CSS 寫成以下這樣:
.page { color: black; color: green\9; /* IE6, IE7, IE8 */ *color: blue; /* IE6, IE7 */ _color: red; /* IE6 */ }
由於我們有 4 個不同的 color 屬性定義,不同瀏覽器版本套用這些屬性時就會有不同的結果出現:
IE9會先套用正常的 color: black; 屬性,套用值為 black
剩下三行的定義 IE9 都看不懂,所以會自動跳過
IE8會先套用正常的 color: black; 屬性,套用值為 black
第 2 行的 color: green\9; 它也看的懂,所以套用值會變成 green
剩下兩行 IE8 都看不懂,所以會自動跳過
IE7會先套用正常的 color: black; 屬性,套用值為 black
第 2 行的 color: green\9; 它也看的懂,所以套用值會變成 green
第 3 行的 *color: blue; 它也看的懂,所以套用值會變成 blue
最後一行 IE7 看不懂,所以會自動跳過
IE6會先套用正常的 color: black; 屬性,套用值為 black
第 2 行的 color: green\9; 它也看的懂,所以套用值會變成 green
第 3 行的 *color: blue; 它也看的懂,所以套用值會變成 blue
第 4 行的 _color: blue; 它也看的懂,所以套用值會變成 red
就是這樣的一個計算邏輯,可以讓樣式表在不同 IE 版本之間進行差異化設計。當然,除了這個範例之外,你還能依據上述各種 CSS Attribute Hacks 的語法與支援的 IE 版本自行變化組合。
請注意:上述樣式的順序性非常重要,因為比較晚定義的樣式會取代較早定義的樣式,所以你必須把最多瀏覽器版本看的懂的樣式寫在比較上面,這樣才能達到 CSS Hack 的效果。
選取器類型的密技 ( Selector Hacks )
選取器類型的 Hacks 就是找出不同瀏覽器之間解析選取器 (Selector) 的瑕疵來判別不同的瀏覽器或版本,這種類型的 Hacks 不止 IE 專屬,你還可以將這種類型的 Hacks 運用在其他的瀏覽器裡,而這裡的語法也比 CSS Attribute Hacks 的語法更奇怪。
只有 IE6 才能解析的選取器,在選取器名稱之前加上 * html
只有 IE7 才能解析的選取器,在選取器名稱之前加上 *+html 或 *:first-child+html
*:first-child+html #style1 { color: red }
只有 IE8 才能解析的選取器,在整個 CSS 樣式規則前後用以下 @media \0screen 定義
@media \0screen { .style1 {color: red;} }
只有 IE9 才能解析的選取器搭配屬性 Hack,在選取器名稱之前加上 :root 與屬性值後面加上 \9
:root #style1 {color: #FF0000\9;}
只有 IE7, Firefox, Safari, Opera 才能解析的選取器,在選取器名稱之前加 html>body
html>/**/body #style1 { color: red }
只有 Opera 9.27 以下與 Safari 2 才能解析的選取器,在選取器名稱之前加 html:first-child
html:first-child #style1 { color: red }
只有 Safari 2 ~ 3 才能解析的選取器,在選取器名稱之前加 html[xmlns*=""] body:last-child
html[xmlns*=""] body:last-child #style1 { color: red }
只有 Safari 3+, Chrome 1+, Opera9+, Firefox 3.5+才能解析的選取器,在選取器名稱之前加 body:nth-of-type(1) 或 body:first-of-type
body:nth-of-type(1) #siete { color: red } body:first-of-type #ocho { color: red }
只有 Safari 3+, Chrome 1+ 才能解析的選取器,在整個 CSS 樣式規則前後用以下 @media 定義
@media screen and (-webkit-min-device-pixel-ratio:0) { #style1 { color: red } }
只有 iPhone 與 Mobile Webkit 的瀏覽器才能解析的選取器
@media screen and (max-device-width: 480px) { #style1 { color: red } }
只有 Safari 2 ~ 3.1 才能解析的選取器,在選取器名稱之前加 html[xmlns*=""]:root
html[xmlns*=""]:root #style1 { color: red }
只有 IE6, IE7, IE8 才無法解析的選取器,在選取器名稱之前加 :root *>
:root *> #style1 { color: red }
只有 IE6, IE7, IE8 才無法解析的選取器,在選取器名稱之前加 :root *>
:root *> #style1 { color: red }
只有 Firefox 1.0+ 才看的懂得選取器,在選取器名稱後面加上 , x:-moz-any-link
#veinticuatro, x:-moz-any-link { color: red }
只有 Firefox 3.0+ 才看的懂得選取器,在選取器名稱後面加上 , x:-moz-any-link, x:default
#veinticuatro, x:-moz-any-link, x:default { color: red }
只有 Firefox 3.5+ 才看的懂得選取器,在選取器名稱前面加 body:not(:-moz-handler-blocked)
body:not(:-moz-handler-blocked) #veinticuatro { color: red }
說實在的,這些 Hacks 語法真有點複雜,但當網頁設計師被客戶要求克服各種瀏覽器版本的樣式差異時,也不得不學會這些密技才能滿足客戶要求。但話說回來,一般客戶頂多就是要求網頁要能夠相容於 IE6 ~ IE9 這些瀏覽器而已,依照筆者多年來的網頁建置經驗,其他像是 Firefox, Safari, Opera, Chrome 根本不會有相容性的問題,如果有客戶要求你要針對 Firefox, Safari, Opera, Chrome 進行相容性網頁設計,你大可要求客戶升級到最新版,不然還真做不下去了。 ^_^
相關連結:
Downlevel Hidden / Downlevel Revealed
Personal CSS Hacks for IE6, IE7, IE8, IE9
In defense of CSS hacks — introducing “safe CSS hacks”
CSS hacks, CSS filters-CSS 區隔各類不同瀏覽器 [5-] @ 網頁藝術思考
4 Types of CSS Hacks for Web Designers and Developers
(2) IE 條件式註
由於 CSS Hack 技巧是運用許多「非標準」的寫法來達到開發相容性網頁的手段,如果你採用 W3C 提供的 CSS 驗證服務來驗證這些含有 CSS Hacks 的樣式表,將會得到許多格式的錯誤,不過即便如此,這些 CSS Hacks 目前還是能夠正常的運作,只能說它有點不安全而已。
所謂「不安全」是因為這類語法是透過各瀏覽器解析 CSS 規則的瑕疵來達成目的的,例如只有 IE6 才能解析的屬性是在屬性名稱之前加上一個底線 ( _ ) 即可達到,這樣的語法「目前」在 IE7, IE8, IE9 以及其他瀏覽器都看不懂,但如果哪天 IE11 或 Chrome 20 又不小心可以解析這類特殊的 CSS Hacks 怎麼辦?這就是一個對未來不確定的風險,所以也有人提到如果可能應該盡量減少使用 CSS Hacks 的語法,但如果不用 CSS Hacks 語法,那我們要如何做到跨瀏覽器版本的相容性呢?沒錯,這就是這一節的重點:使用 IE 條件式註解。
IE 條件式註解 (Conditional Comments) 是 Internet Explorer 獨有的相容性技術,在其他非 IE 的瀏覽器中並沒有類似的設計,條件式註解並非 W3C 標準,但這樣的技術的確非常實用,針對不同的 IE 版本可以非常安全的套用不同的網頁內容,又不會影響其他非 IE 瀏覽器的網頁呈現。
有別於 CSS Hack 技巧,IE 條件式註解是寫在 HTML 裡面的,接著我們來看一下條件式註解的語法,以下這段條件式註解寫著一個判斷條件式[if IE 8] 所代表的意思是:當 IE 版本為 8 時,顯示在註解內的那段綠色文字,若使用者使用的 IE 版本為 9 或其他非 IE8 的版本,則會將這一整段視為註解文字。
請注意:上述紅字部分,你不能在這幾個字元之間加上空白字元,要完全一樣才可以生效。
我們再寫一個比較完整的例子,我們可以用條件式註解來選擇不同的 HTML 內容來輸出:
真正輸出的時候只會輸出判斷條件為「真」的內容,如下圖示:
同樣的網頁,若用非 IE 瀏覽器開啟(在此我用 Google Chrome 開啟)其畫面如下,所有內容都被瀏覽器視為註解了!
這時你可能會想說,如果條件式註解內的內容也想讓其他非 IE 瀏覽器顯示有辦法嗎?答案是肯定的!
條件式註解還有另一種特殊的表示法,就是把條件式註解變成條件式標籤,如下範例:
if IE 8]>此內容只會在 IE8 與其他非 IE 瀏覽器顯示
請注意:這段「條件式標籤」跟之前的版本差別僅在於把 -- 字元給刪除,這段條件式標籤在其他非 IE 瀏覽器下,由於看不懂這種表示法,這些瀏覽器會把他當成一個看不懂的標籤,因為上下兩段都是 < 開頭與 > 結尾,而瀏覽器只要看到不認識的 HTML 標籤就會自動忽略,也因此綠色的部分就會正常顯示在瀏覽器上,因此,條件式標籤也是可以用在跨瀏覽器的應用上。
在條件式註解的判斷式中還可以寫許多複雜的判斷條件,以下是判斷條件的語法:
! NOT 邏輯運算 [ 注意: 判斷 !IE 時應該要用條件式標籤才對 ]
if !IE]>任何非 Internet Explorer 瀏覽器
lt 小於
lte 小於等於
gt 大於
gte 大於等於
( ) 子條件式
& AND 邏輯運算
true 永遠為真的邏輯運算,等同於 [if IE] 判斷式
活用條件式註解或條件式標籤的技巧有很多,你不只可能那來顯示不同的 HTML 內容,還可以用來載入不同的 CSS 檔,這種撰寫技巧又被稱為條件式樣式表 (Conditional stylesheets),如下範例所示,你可以透過條件式註解來完成條件式樣式表的載入,如此一來就可以避免在 CSS 樣式表內使用「不安全」的 CSS Hacks 語法:
還有一種撰寫技巧被稱為條件式類別名稱 (Conditional classnames),這技巧經常用在 HTML5 的網頁裡,我們為了做到不支援 HTML5 的舊版瀏覽器也能讀取正確的樣式,有時會採用這種方式搭配 CSS 撰寫,達到不同 IE 版本也能套用不同樣式的目的。例如在 Initializr 與 HTML5 Boilerplate 這些 HTML5 範本產生器裡都能看到使用條件式類別名稱的技巧。
doctype html> <html lang="en" class="no-js"> <head>
透過條件式類別名稱的技巧,你的 CSS 內容就可以寫成以下這樣,也可以有效避免使用 CSS Hacks:
.style1 { color: black; } .ie8 .style1 { color: green; } /* IE8 */ .ie7 .style1 { color: blue; } /* IE7 */ .ie6 .style1 { color: red; } /* IE6 */
注意事項
微軟已經決定 Internet Explorer 10 之後的版本將移除條件式註解功能,因此下一代 IE 瀏覽器在解析條件式註解時將會與現有其他瀏覽器一樣,針對條件式註解或條件式標籤裡的條件式都會自動忽略,因此該功能只能用在 IE9 以下的瀏覽器裡。相關資訊請參考:Obsolete features in Internet Explorer 10
上一條:已经是最前一篇了
下一條:如何製作在所有版本的IE瀏覽器相容的網頁