iframe標籤在網頁中可以創建一個內嵌框架,通過指定src屬性來調用另一個網頁文檔的內容。和frameset一樣,用它來對網頁結構進行拆分以使網頁的某些部分保持公用,但相對frameset對整個網頁進行框架結構的拆分來說,iframe更加靈活,可以內嵌到網頁的任意地方。由於iframe使用上的這個特點,在一些網頁中得到了大量運用,也導致了一些不適宜的濫用。網頁設計將分析一下iframe這個網頁元素常見的幾種使用方式。
- 製作無刷新響應頁面組件,作為異步交換數據的一種解決方案。這是早期不使用ajax來異步發送請求的一種替代方法,通過在頁面上設置不可見的iframe元素,並將其src屬性指向需要發送請求的頁面地址來發送請求,同域下可以再對返回的頁面進行dom解析來獲取數據。另外一個好處在於繞開了ajax的沙箱安全模型,可以順利發送跨域請求獲得數據,只是這種情況下取不到iframe的document對象。因為它的這個特點,在某些需要跨域請求數據的網頁中依然有應用。這種無刷新是指在數據交換過程中父頁面不刷新而繼續對用戶操作保持響應,實際進行數據交換而被鎖定的是父頁面上內嵌的iframe頁面。這個內嵌iframe頁面根據需要設置為可見或不可見都可以,並不會影響父頁面中的其他元素對用戶的響應。這種效果類似ajax的無刷新,但可以看出其機制是完全不同的。即使gmail作為ajax應用的典範,也結合了很多iframe來實現其優越的性能與用戶體驗。
- 優化頁面的一種方式。使用iframe可以並行加載腳本,解決加載緩慢的第三方內容如圖標和廣告等的加載問題。 google的廣告平台adsense即通過iframe在用戶的站點上投放廣告分享收益,查看分析國內門戶首頁上的廣告代碼也能看到這類技術。也可用隱藏的iframe在網絡壓力較小的時候來預加載比較大的文件到緩存,以便其他頁面使用。預加載的概念可以用firebug分析google首頁,在body標籤裡可以看到:
onload=document.fqfocus();if(document.images)new image().src= '/images/nav_logo4.png '
這樣一句代碼,加載的圖片nav_logo4.png在首頁並沒有用到,但搜索結果列表等其他頁面使用此圖片的時候只需要從緩存讀取,不需要重新下載了。
- 作為針對ie6瀏覽器中浮動層遮不住select控件和flash元素的一種修正(hack)方式。 web2.0時代lightbox(又或thickbox)技術以它良好的體驗與清新的視覺感受成為一種流行效果。這種技術實際上是用一個絕對定位的浮動層覆蓋到原有頁面上,用以呈現文本信息、圖片、表單或其他任意頁面元素,替代了早期web開發中常使用彈出瀏覽器窗口或者瀏覽器自身的消息、輸入控件來與用戶進行交互的方式。舊有方式中,彈出新窗口的腳本經常會被瀏覽器的廣告攔截系統攔截,而瀏覽器自身的消息控件因為會打斷瀏覽器進程,導致瀏覽器中本頁面以及其他通過多標籤進行瀏覽的網頁全部被鎖死而受到用戶體驗研究者的詬病。作為對自己有嚴格要求的一線web前端開發人員,在動手實現lightbox效果的過程中一定會遇到這個問題,絕對定位的層在ie6中遮蓋不了網頁上的select控件和flash,即使樣式設置較高的z-index值也無濟於事。這是因為select元素在ie6中是一個窗體級別的元素,它的優先級大大高於其他所有的html標籤,只有同樣窗體級別的iframe才能遮住它。因此開發者們研究出,把浮動層放到iframe中,或者在浮動層中放置一個iframe就可以解決此問題了。所幸此問題在ie6以後的ie升級版本中得到了修正,但對於還擁有50%+市場佔有率的ie6來說(統計截至發文時間),這個解決方案依然有現實意義。
除了以上三種應用,對於iframe元素也常見一些不恰當的運用。例如在頁面中嵌入過多的iframe框架,通過指定框架外鏈接標籤的target屬性在點擊時來更新iframe,這種用法和frameset類似,達到共用導航的目的。初衷是好,但其中的弊病也毋庸置疑。這樣會導致一個頁面請求過多,上文所提及的雅虎團隊《best practices for speeding up your web site》一文中就明確優化頁面需要使iframe的數量最小,歸納了其三種弊病:
- 即使內容為空也會造成資源損耗(包括客戶端、服務器端);
- 阻滯頁面onload事件觸發(blocks page onload,又有譯作會阻止頁面加載,此處存疑)
- 沒有語義(seo是網站營銷的重要組成部分)
在xhtml1.0的下一個版本html5中,由於frameset標籤對網頁可用性方面產生的負面影響,沒有對它提供支持,這也從側面說明一些問題。
另外,由於內嵌的iframe不能自動適應其內部內容大小,為了保持頁面顯示的完整性,還需要編寫一段javascript腳本來根據iframe內容的變化即時調整其大小。分散的多個請求再加上需要javascript腳本來修正更增加了多iframe頁面系統運行的風險。那麼,有沒有什麼好的方法能保持部分頁面內容公用呢?服務器端早就給我們提供了解決方案,asp中的include,php中的require方法,都是用來包含一段已有的代碼到程序中,這樣同樣能實現頁面的某個部分(如導航菜單、頁腳)公用,但是運行之後作為一個完整的頁面輸出,有效地減少了客戶端請求,同時也不存在iframe的高度自適應的問題。