Whatever:hover – 無需javascript讓IE支持豐富僞類

絕大部分現代瀏覽器支持 css 中的 :hover 僞類選擇器,可以用於所有 html 元素。這很酷,因爲這使你可以僅通過 css 來對錶格行(<tr>)應用鼠標滑過事件(mouseover)時的特殊效果。然而,萬惡的IE,對 :hover 僞類頂多只提供了有限的支持,具體支持的程度要取決於你的IE瀏覽器的具體版本。
Whatever:hover 是一個小小的腳本,它可以迅速、自動地爲IE6,IE7,IE8添加標準的 :hover、:active 和 :focus 僞類支持。第三版引入了 ajax 支持,意味着通過 javascript 動態添加到文檔中的任意html元素也同樣可以在IE中響應 :hover、:active 和 :focus 樣式。
如果你已經對使用 whatever:hover 很熟練,現在只是想下載它,你可以直接跳轉到獲取最新版本。而對於其它想深入瞭解它的人,請繼續閱讀。

使用方法

你只需要將 whatever:hover 鏈接到 body 元素就可以了。注意這裏的 behavior 屬性中的 URL 是相對於 html 文件的,而不是像背景圖片地址一樣是相對於 css 文件的路徑。
body { behavior: url("csshover3.htc"); }

工作原理

所有的瀏覽器都提供了一些方法,讓你用 javascript 查詢樣式表中定義好的規則或者動態地插入新規則。正常情況下,IE 對所有它不支持的規則返回 “unknown”。例如:一條關於 “div p:first-child” 的規則將會被改成 "div p:unknown”, 而一條關於 "p a[href]” 的規則將整體地作爲 "unknown" 返回。幸運的是 IE 把 :hover 僞類認爲是它支持的樣式規則,並且會將它保持原樣。
IE 還支持所謂的行爲(behaviors),不僅包括預定義的功能比如動態加載內容或者持續數據存儲,也包括你可以在一個後綴爲 .htc 或者 .hta 爲的文件中創建的自定義行爲。這些行爲通過 css 實現與 html 節點關聯,並“增強”這些被指定行爲中的樣式選擇器選中的節點。
綜上所述,創建一個行爲來查找樣式表中 IE 不支持的元素,並以一些其它手段“欺騙”影響的到元素讓它們應用樣式表中關聯的樣式。這個複雜的操作中包含的步驟大致可以描述爲:
  • 在所有的樣式表中搜索 IE 不支持的 :hover 僞類規則;
  • 插入一條 IE 支持的,例如帶 class 名稱的新規則;
  • 最後,設置腳本事件來切換目標元素的 class 名稱。
通過這種方式,:hover、:active 和 :focus 就可以得到(IE 的)支持了。而作爲開發人員,你除了包含這個行爲以外不需要做任何事。所有的工作都將自動完成。
與第1版和第2版比較,第3版對動態加入的 html (ajax) 也同樣支持。另外還有一個改動是原來第1版和第2版採用的是在頁面加載事件中主動搜索影響到的元素,而在第3版中改爲藉助表達式(expressions)讓節點自己回調。關於這部分你可以閱讀帶註釋的版本獲取更多細節。

示例:菜單效果

:hover 一個很常見的用途就是用列表創建菜單系統。用這個行爲來創建一個兩級的菜單系統是再容易不過的事情了。例如,如果你從 suckerfish dropdown (一個帶有下拉菜單的網頁,關於這個頁面和效果的描述,參見 A List Apart article)上把 javascript 刪除掉了,它仍然能正常工作。
但是多級的菜單需要做不同的處理。這是由於 IE 不支持子選擇符 ‘>’,子選擇符可以完美地顯示下級子菜單,而不是連更深層的菜單一起顯示出來。
li:hover > ul { /* 在 IE 下無效 */ }
有一種可供選擇的方法可以只使用簡單的子孫選擇符來模擬這種行爲(主要是針對 IE)。還有種不太成熟的方法是應用多個類定義,但是更簡單的方法是利用 CSS 選擇符的不同優先級(specificity).每一條 css 規則都有特定的重要等級,這個等級可以簡單地根據一條規則中的不同元素來計算。以元素名稱爲基準值 “1″,類、僞類和屬性選擇符重要性(權重)爲 “10″,然後元素 id 爲 “100″。比如下面的例子。
ul ul { display:none; }
li:hover ul { display:block; }
這樣做能夠生效的原因,就是選擇符的優先級不同。第一條規則只包含兩個元素名稱,這樣它的權重值(優先級)就是2。第二條規則也包含兩個元素名稱,但是 :hover 僞類的權重值(優先級)是10,所以加起來的值就是12。由於第二條規則比第一條規則優先,因此被鼠標滑過的 li 元素內部的 ul 將被顯示。
那麼這個對於解決 > 子選擇符的問題有什麼幫助呢?是這樣,如果一條權重值(優先級)爲12的規則定義所有的子菜單都要顯示,我們只需要創建一條權重值(優先級)大於12的規則來把下一級的菜單隱藏起來。然後,那個菜單又需要另一條優先級更高的規則來顯示,一直循環下去。對於3級的導航來說,需要的 css 代碼短得讓人意外:
/* 2 和 13 */
ul ul, li:hover ul ul { display:none; }
/* 12 和 23*/
li:hover ul, li:hover li:hover ul { display:block; }
這種方式可以無需附加任何類樣式實現無限級嵌套菜單(4級或更多級需要需要繼續添加更多規則)。

腳本事件的性能優化

現在還剩下一件事需要考慮。.htc 文件在所有樣式表文件中搜索 :hover 規則,並且按照 css 文件的定義對所有它認爲需要用腳本處理停留效果的元素附加鼠標滑過和移出事件。爲了找出這些(被影響的)元素,所有去掉 :hover 僞類選擇到的元素以及被 :hover 僞類修飾的元素本身,都會被選擇並且進行處理。一條類似這樣的規則
#menu li:hover ul { ... }
…將會被調整成下面這樣來查找所有可能需要響應鼠標滑過事件的元素:
#menu li  { ... }
很顯然這會選中整個菜單中的每一個 <li> 元素,並對其中一大堆不需要鼠標事件(在當前情況下)的元素附加事件。這個問題可以很輕鬆地得到解決,我們可以對包含子菜單的列表元素添加一個類樣式,比如 "folder"。這樣一來,調整(去除:hover)之後的樣式規則變成了
#menu li.folder { ... }
…可以高效地直接選中那些真正需要事件的元素。缺點是爲了改善腳本的性能,你需要添加一個類樣式(這個類樣式的添加純粹是爲了視覺效果,而且放棄了 li:hover 方式實現菜單的通用性)。但是,從另一個角度考慮的話,也許你反正也要用一個類來把這些列表元素與普通元素區別開來,那就無所謂了。
爲了直觀地說明上述問題,請查看綜合示例。希望你喜歡。

文件下載及更新說明:

v3.00.081222 (:hover, :active 和 :focus)
v1.42.060206 (:hover 和 :active) 下載 | 查看
v2.02.060206 (:hover, :active 和 :focus) 下載 | 查看
說明:
說明1:如果在使用 whatever:hover 的過程中遇到問題,請 讓我知道! :) 由於第3版比較新,可能會存在一些無法預知的問題。
說明2:確保你的web服務器把 htc 文件按照 text/x-component 的 mime類型發送。關於這方面的更多信息,可以參閱 Aldo的個人博客。如果你的主機支持 .htaccess 文件,可以添加下面這行代碼:
AddType text/x-component .htc
說明3:第三版支持在 IE6 以上版本中使用 :hover 和 :active,對 IE7 和 IE8 還支持 :focus。由於表達式(expression)在 IE8 標準模式下不支持,所以 whatever:hover 只在 IE8 的怪異模式(Quirks Mode) 下運行。實際上在 IE8 標準模式中也根本不需要這個腳本了。
說明4:如果使用這個腳本之後網頁變慢,請嘗試對更加具體的選擇符運用 :hover 僞類,比如添加元素名稱、使用元素id,或者類名稱。例如:"div#someId li.group:hover”, 而不要只用 ".group:hover”。這樣能夠很大程度上減少搜索和解析時間,並能減少需要應用的事件。請閱讀 性能優化 獲得更多信息。
說明5:第2版也支持 :focus 僞類,僅限於 A、INPUT、和 TEXTAREA元素。但是,由於類似 "input:focus" 這樣的選擇符被 IE 的樣式表對象返回爲 "input:unknown",腳本將基於這些 "unkonwn" 規則來附加獲得焦點和失去焦點事件,這個問題同樣存在於其它瀏覽器無法識別的僞類。因此,使用2.0版本的時候,你無法在 IE 中對 A、INPUT和 TEXTAREA 元素應用瀏覽器無法識別的僞類,因爲他們統統都會被處理成獲得焦點樣式。如果你確實需要這個功能,請使用1.4版或者3.0版。
Naar Voren (一個關於web開發的德語網站)上,有我用德語寫的一篇關於用純css 在菜單系統中使用 :hover 的更詳細的文章(德語版)。對於不懂德語的網友,可以查看該文章的英文翻譯版
非常感謝 Arnoud Berendsen 和 Martin Reurings 提供的創意和支持,感謝 Robert Jan Verkade 和 Naar Voren 上的朋友們發表我的文章,還要感謝 Eric Meyer 對這個腳本給予支持和在他的書裏提到我的這個網頁(指 《Eric Meyer談CSS(卷2)》 第六章》——譯者注)。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章