到目前為止,我已經嘗試了幾種移動終端尺寸適配的方案。從最初的百分比單位,到rem,到vh,vw,再到這些適配單位結合flex布局的使用,我還在不斷的優化和嘗試新的方案,我也嘗試把這幾個方案結合起來使用。應用到生產環境後,取得了壹些小成績,也發現了壹些小缺點。下面將對這些方案進行簡單的討論,並分享作者在使用時遇到的壹些問題以及使用場景。
百分比單位是妳學習前端時接觸到的最快的大小單位,%會根據父元素的大小來分配。如果父元素是壹個200px * 400px的盒子,子元素設置為width: 80%,則寬度將設置為160px。同樣,百分比將根據父元素的大小來計算。當父元素的大小固定時,百分比非常有用。那麽如果父元素沒有固定的大小,那麽如果按照子元素的大小來擴展呢?然後我們會發現實際顯示的高度是0,寬度卻不是0。不設置大小的父元素的寬度將繼承其父元素的寬度,而高度則不會。默認值為0。那麽我們的子元素設置的百分比和寬度是正確的,高度是0。因為百分比是根據父元素的大小計算的,如果父元素的寬度不為0,則可以計算出非零值,如果高度為0,則只能計算為0。因此,當父元素沒有固定的大小,需要由子元素擴展時,height使用的百分比將得到0。因此,應謹慎使用高使用百分比。那麽,如果我們用百分比來適應不同尺寸的手機屏幕,保證UI設計能夠在所有尺寸的手機屏幕上以正確的比例重現,那麽我們就應該在根元素處設置具體的大小,這樣就可以基於這個大小來逐級計算百分比。
其實我們可以直觀的發現,如果我們的UI需求是壹個可以無限加載的滾動列表,那麽在根元素上就無法設置具體的高度,百分比在高度上就無效了。那麽我們只能為列表項設置具體的高度,但這並不能保證不同大小的列表項比例與UI設計壹致。這是百分比單位自適應的壹個明顯缺點。但是,如果UI設計不要求各個比例與UI壹致,那麽百分比單位仍然可以使用。
然後,由於百分比單位不能滿足我們的需求,我們開始尋找新的方案。這時候就很容易找到大家壹直在說的rem單元了。rem也是web支持的許多大小單位之壹。和em很像,那麽em和rem有什麽區別呢?Em基於父元素的字體大小屬性,而rem基於根元素的字體大小屬性。如果父元素設置為font-size: 50px,那麽子元素的1em == 50px。而且,如果子元素沒有設置font-size,默認情況下會繼承父元素的font-size,所以子元素的子元素也滿足1em == 50px。那麽可以很直觀的理解,如果子元素設置了自己的font-size,那麽上面的等式就不再滿足了。所以,如果父元素需要設置自己的font-size,而它的子元素又想做em來基於祖父元素(父元素的父元素)設置大小的話,就會陷入尷尬的境地。
那麽快速眼動有什麽不同呢?我們前面提到過,rem基於根元素的字體大小。如果根元素設置為font-size: 50px,我們將通過在其任何子元素或嵌套的多級子元素中使用width: 1rem得到width: 50px的反饋,而不管父元素的font-size設置為什麽值。也就是解決了em單位上面提到的尷尬局面。但是需要註意的是,由於font-size可以壹步壹步地傳遞下去,所以最好在根元素下的第壹級元素上將font-size設置回默認值。這樣做的原因是,如果在壹步壹步嵌套的過程中出現了壹個文本節點,但是沒有設置對應的font-size,那麽這個文本節點的字體大小就會是根元素設置的font-size,字體會很大。如果大多數文本節點需要相同的字體大小,那麽在每個文本節點上重新設置字體大小的值是不方便的。因此,如果根元素下第壹級的子元素設置了font-size的大小,那麽所有文本節點都將繼承font-size的值,而不是根元素的值。因此,沒有必要在每個文本節點設置字體大小。
EM&簡介;Rem這兩個單位,我們發現EM &;Rem有自己適合的使用場景,但相比之下,rem可能更適合整體的適配方案。那麽應該如何確定1rem的大小呢?網上資料有很多確定的方案,其中主要有兩種核心計算方法。
第壹種是根據尺寸範圍來確定,即在移動終端中的各種尺寸中,劃分多個範圍,並且在每個範圍中確定壹個固定值。其具體實現是結合媒體查詢,在不同的範圍內為屏幕大小設置壹個固定值,以便進行適配。
另壹種是根據屏幕的寬度和設計稿的寬度計算得到壹個數值。這種計算可以在所有維度上得到壹個對應的唯壹值。它的具體實現是通過js獲取設備的屏幕寬度,然後用設計稿的寬度進行轉換,計算出壹個值,再通過js動態設置為根元素。
這兩個思路基本都是上面的,只是具體換算計算,不同公司的思路不同。具體換算可以點擊這裏。我自己的方案是第二種,根據屏幕的寬度和設計稿的寬度來換算。那麽下面就來介紹壹下作者是如何轉換的。
其實筆者的換算計算方法和網易手機是壹樣的,只是我沒有網易那麽理解這個換算計算方法。只是這個樣本計算會很方便。因為我拿到的設計稿是750 mm寬,而我壹開始是想把750px換算成75rem,那麽實際設備的1rem的大小,用75除以屏幕寬度就是1rem(實際設備),也就是1rem(實際設備)= w(屏幕寬度)/75。但是後來我試著發現1rem=10px(設計稿)的計算在chrome上會失效。chrome最低只能達到12px,但實際算出來的1rem遠小於12px,因為手機的寬度大多在360-480之間,是這樣算出來的。後來改成了1rem=100px(設計稿),意思是750px=7.5rem .全部會是1rem=10px或者1rem=100px,就因為這樣的計算,很方便的刪減了設計稿的大小。如果設計稿有130px * 80px的元素,那麽只需要1.3REM。計算時只需要除以100,在切圖時直接計算即可,不需要用計算器壹個壹個計算。後來這個方案用久了,看到上面鏈接的博客被引入網易手機,想的比想象的多了很多,才發現自己瞎了眼,遇到了死耗子。
這個方案壹直是我移動終端適配的主要選擇,直到我發現在ios的webview上使用rem動態加載網絡圖片時,圖片無法顯示。經過調查,我發現通過js接口獲取的網絡圖片在加載時無法正確顯示。這也是我開始思考結合rem有沒有什麽更好做的更好。因為我在微信做h5的時候,用rem從來沒有遇到過刻度錯誤。在我看來,rem在大部分接口上還是很好適應的。但是我們在使用的過程中也發現了壹些小問題,因為rem的單位計算是基於7.5的屏幕寬度,1rem(實際設備)的值不能保證是整數,所以設計稿上面的壹些小空格,比如小於10px的,在css中會寫成0.06rem,但是因為1rem,但是,如果間距是px做的,那麽rem就會變得不準確,特別是在7.5rem本身就是壹個屏幕寬度,但是加上px之後,去掉px之後還剩下多少rem可以算出來。
然後我開始全面擁抱flex。使用flex布局後,我發現結合flex和rem可以做得更好。因為如果間距用px,部分元素用rem,那麽剩下的可以直接用flex拉伸擴散,不用擔心去掉px還剩下多少rem。移動端基本兼容flex,可以直接使用,但是需要添加相應的內核前綴。flex的使用極大地優化了布局上的書寫。
後來,大眾&;vh對,vw其實是基於window.innerWidth,vh是基於window.innerHeight 100vw等於屏幕可視範圍的寬度,100vh等於屏幕可視範圍的高度,也就是移動端webview的大小。而且發現vw很像750px=100rem(設計稿)的情況。在這種情況下,1rem的大小和1vw是壹樣的,所以vw的使用基本上和rem差不多。而壹個屏幕的寬度等於100vw,也是像percentage,但是vw是基於屏幕寬度,而不是像percentage壹樣基於父元素,所以在水平適配上取得了非常好的效果。但是vh呢因為有時候需要用壹個屏幕的寬度和高度做壹個H5界面,這個時候vh就發揮作用了。壹般情況下,100vh是壹個屏幕的高度。然而,在使用vh的過程中有壹個問題,就像帶有輸入標簽的壹屏H5註冊頁面壹樣,需要用戶填寫信息。將背景圖像的高度設置為100vh。當輸入框被聚焦時,手機鍵盤彈出,然後背景圖像會被壓縮,因為屏幕可見高度是壹屏高度減去手機鍵盤高度,所以100vh會變成這個高度而不是壹屏高度。這個問題是使用vw和vh時遇到的唯壹問題。我還沒想出好的解決辦法。如果鍵盤不會彈出,需要壹個屏幕的高度,強烈推薦vh。另壹方面,大眾還沒有遇到任何問題。
在改編中嘗試了幾種方法,每種方法都有其優缺點。但如果根據使用場景選擇組合使用,可以達到相當不錯的適配效果。