雖然國內此技術應用就像是打不著的打火機,沒法跟如火如荼的歐美相比。但是,畢竟趨勢是向前發展的,總會迎來遍地開花的時候,只是時間的長短而已。
本文所涉及的三個關鍵技術點,偽類(IE8+), js(getComputedStyle, IE9+)以及media queries(IE9+)都需要現代瀏覽器的支援。因此,如果您不是做HTML5開發,或是從事的是面向福士的普通web頁面,本文內容沒有任何實用價值。有協助的,估計就是拓寬思路,增長眼界了。因此,本文內容很快就會歸於沉寂,或許5年之後,某君陰差陽錯進入此處,發現此文,會不由得驚歎——原來很多年前就有人介紹這個技術啦!但是,曆史的發展與推動少不了那些湮沒在曆史中的開拓者。
media queries可以讓裝置在不同尺寸下應用不同的CSS樣式、布局等。以適應手持功能、普屏顯示器、寬屏顯示器,以及未來冰箱上的連網顯示器,汽車上的數位裝置等。然後,僅僅通過CSS做布局可能無法應對所有的互動請求。
舉個簡單例子,我們開啟瀏覽器可能處於非最大化狀態,此時,如果作為普屏處理,載入的圖片可能就是128*128的小尺寸圖片。但是,當我們最大化以獲得更好閱讀體驗的時候,需要使用更大尺寸的圖片256*256, 使用media queries? 拜託,CSS只能改變外在的尺寸,你難道要2倍尺寸展開?顯然,更合理的做法是載入256*256尺寸的中等尺寸圖片。以目前的技術而言,估計除了使用JS修改圖片src外,很難有其他更可用的方法了。
OK, 現在問題來了,如何讓JS的修改與CSS布局改變同步呢?
二、CSS互動與JS互動同步問題
如何讓CSS樣式、布局改變的時候,同時準確觸發JS的互動呢?
方法一、直接寬度/高度值匹配
何意?CSS3 media queries跨界觸發一般都有一個寬度或高度值,或是color(很少使用)。例如,普屏圖片寬度128*128,可能就是如下CSS:
代碼如下 |
複製代碼 |
@media screen and (max-width: 1024px) { img { width: 128px; height: 128px; } }
|
意思就是screen(螢幕)寬度不超過1024像素(max-width:1024px)的時候,圖片寬度是128像素,高度也是128像素。
因此,我們可能通過瀏覽器視窗尺寸改變的resize事件中捕獲瀏覽器視窗尺寸,與1024對比,如果小於則觸發對應的普屏事件處理,大於,則寬屏處理。
代碼如下 |
複製代碼 |
window.addEventListener("resize", function() { // window.innerWidth IE9+瀏覽器支援 if (window.innerWidth <= 1024) { // 普屏處理 } else { //寬屏處理 } }); |
確實是簡單高效的方法。但是,也是有不足的。
① 可維護性
一個載體所對應的數值是會經常變的。例如,小胖今天體重148斤,明天喝碧生源廁所來回幾個小時,可能就只有145斤了。同樣的,對於1024這個值,變動的幾率是很大的。變動其實沒什麼,麻煩的是下面的JS中的判斷的數值與CSS中的限制是要一致的。也就是CSS寬度閾值改變,JS也要跟著變。顯然,這種高耦合增加了後期的維護成本。
② 寬度的計算與不確定性
window.innerWidth返回的是視窗內部寬度(不包括瀏覽器的框框),單位是像素。但是,width屬性的單位並不固定。有些網站,可能使用em, %或最新的vw, rem, in等(完整單位參見之前“CSS長度值及時間、頻率、角度單位”一文)。
而這些單位的寬度轉換成px就需要計算,而這些單位很多是相對的,例如em是與字型大小相關的,如果網頁的字型大小被使用者手動改變(視力不佳使用者,或是“Ctrl + 加號”的誤操作),可能你之前按照12像素比例的寬度計算就會不準確。這就是寬度計算的不確定性。
可見,我們有必要尋求更佳的同步方法。什麼呢,就通過CSS本身!
通過CSS本身?
比方說吧(雖然這個例子實用性不佳),我們通過media queries讓圖片寬度變成128像素,就可以通過檢測圖片應用的寬度判斷當前裝置狀態。
當然,這裡只是舉例,其實這比上面1024px方法更搓,因為,牽扯到實際樣式的CSS是會經常變動的,JS顯然不能與之高耦合。
那該如何應用呢?很簡單,應用在不會使用的元素,不會產生額外影響的CSS屬性。例如在<head>標籤上使用z-index屬性(from Stephanie)。
代碼如下 |
複製代碼 |
@media screen and (min-width: 45em) { head { z-index: 2; } } |
不過,根據Jeremy Keith的測試,Webkit瀏覽器貌似不支援,其返回的z-index值是auto, 不是數值2. 我那熱乎乎的小心臟,瞬間冰凍,啊~~
應用在<body>標籤上到是可以的,不過,由於body標籤暴露在外,參與CSS布局,如何其設定了定位屬性(relative, absolute等),z-index立馬勃起,如果裡面在層級複雜點,哦呵呵,兄弟你把妹的時間估計要陪代碼咯!
不過,對於一般的頁面(不是類似遊戲頁面,投影片頁面的頁面),只有某些藝高人才敢在body上增加定位屬性(違背最小化影響原則 – part 7),因此,在body上設定z-index屬性一般問題不大,但是,從可理解性上講,z-index弱了點。因為,z-index值一般是數值。你說:
800~1024 z-index:1;
1024~1280 z-index:2;
1280~1440 z-index:3;
1440~1680 z-index:4; 兩個月後,你在看JS中,zIndex的1, 2, 3, 4,你還記得對應的數值範圍嗎?別人經手你的代碼,知道各個數值對應的含義嗎?(別跟我扯注釋~~)
因此,我們需要尋求更佳的方案。
方法二、body標籤+偽類+content內容產生
因為每個頁面都有body標籤,在該標籤上打標記便於整站通用。
這裡的偽類指:after, :before亦可,因為,使用該CSS屬性與實際用途衝突機率要比z-index屬性小多了,更加安全。
content內容產生我專門寫過一篇文章:“CSS content內容產生技術以及應用”,後來又結果偽類屬性寫了篇:“:after偽類+content內容產生經典應用”。您有興趣可以看看。而這裡,則是一個新的應用典型了。
使用content內容產生的最大好處在於,我們可以隨意定義裡面的內容(z-index只能數值),例如:
{ content: "普屏"; }
顯然,這個描述性的文字是很泛的,概括性強,不會因為1024px變成980px而跟著變動,而且,含義明顯,一目瞭然。
因此,上面的一番分析總結,body:after + content是相當好的一個方法。
我們唯一剩下的技術痛點就是如何使用JS擷取content的內容。噹噹噹噹,前幾天的寫的“擷取元素CSS值之getComputedStyle方法熟悉”一文內容就派上用場了。