一、前言
昨天嘮叨了哈沒用的,今天說點有用的把。先說一下響應式布局吧,我一直認為響應式布局的分項目,一下布局簡單得項目做響應式還是可以可以得。例如博客、后台管理系統等。但是有些會認為響應式很牛逼,尤其是在不懂前端的人眼中,一味的追求響應式布局,我覺得復雜的布局項目做響應式還不如做二套樣式,因為響應式的樣式混在一起真的維護起來是恨費勁的。可能我說的不對,但是發表 一點點自己的看法。說道這里就想說一下移動端的布局,有很多人就是想把手機端得程序兼容ipad,我就覺得這個很不可思議為什么要這么做得,命名手機端的和ipad的設計模式以及操作樣式都不一樣。為什么還要把它們弄做一起的,維護起來的比較麻煩。還不如做成兩套樣式或者ipad直接讓pc來兼容。pc的設計方式和ipad還是比較接近的。如果非要用移動的樣式稍加改成ipad,個人感覺這種方案極不好。不知道大家的看法如何?
接下來我就說一下布局方式吧,目前比較流行的布局方案就是百分表啦。貌似百分之九十以上得觸屏版都是這么做得,這種做法可以說是不會出現什么大問題,但是也會有幾個小的問題,例如屏幕大的手機和比屏幕小差距之大,尤其是在比價斤斤計較的設計面前你是無法說清楚的,她會一直問,為什么這兩個手機的布局差距這么大呢?其實我想說,我他媽怎么跟你解釋呢。。。此處省略1000個字。在就是布局起來也比較麻煩,真心麻煩。當然肯定有更好得方案拉,於似乎我就想出了一個比較好的解決方案,頂寬布局。
二、320定寬布局
當時我也想了很多方法,但是一直沒有好的解決方案,曾經看了plums的一篇這個博客,當時看完哇塞,這不是正式我想要的嘛。可是嘗試了多次發現這個方法的兼容性有很大的問題。最后還是放棄拉。於是乎我就開始琢磨,怎么才能更好得兼容所有的機子呢。就想到了縮放,viewport不就干這個的嘛。二話不說就嘗試一下viewport里面得一個屬性initial-scale,思想很簡單,在頁面渲染的時候我計算一下手機的寬度,然后我在跟我頂寬布局的寬度一做比較。那么不就可以實現了自動縮放嘛。可是我嘗試的結果是,日的,這個屬性各個瀏覽器支持不好。其實我覺得如果這個屬性大家都能統一的支持,那就是完美的解決方案拉。可是誰讓我們是程序猿呢。只要靠自己吧,要不然jquery也不會誕生。我們就是要在一個個坑中走過來呀。
接着就想到了scale哈哈,css3里面得縮放,不過后來發現用這個字體什么的會虛掉。所以想起了zoom屬性,從這可以看出來我也是干過pc的,當時的ie6的清楚浮動有一種方式就需要加一個zoom為0,這個就不錯嘛。話說回來了。這個在nativeapp里還是沒有太大問題得。不過還是有一點小坑,就是計算margin以及scroll的時候就出來個縮放系數的問題。不過還好,只要你把常用的組件寫好除以或者乘以這個縮放系數就可以搞定啦哈哈。這種方式就可以解決小伙伴們百分比布局的痛苦拉。尤其是不用去計算那些百分值多少百分值多少拉。廢話不說啦,上代碼,
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 5 <meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 6 <meta name="format-detection" content="telephone=no"/> 7 <title>GreatBoy</title> 8 <style> 9 /*-----css Reset end-----*/ 10 body,h1,h2,h3,h4,h5,h6,p,ul,ol,form{ 11 margin:0; 12 padding:0px; 13 } 14 body{ 15 font-family: "Arial"; 16 font-size: 100%; 17 margin: 0px auto; 18 display: none; 19 } 20 #wrapper{ 21 width:320px; 22 margin: 0px auto; 23 position: relative; 24 } 25 /*-----css content start-----*/ 26 27 .nav img{ 28 width:100%; 29 display: block; 30 } 31 32 </style> 33 </head> 34 <body> 35 <div id="wrapper"> 36 <div class="nav"><img src="http://p1.jmstatic.com/banner/75/mobile_app/24326_0.jpg"/></div> 37 <div id="container"> 38 <div id="user">用戶信息<span id="userinfo"></span></div> 39 </div> 40 </div> 41 <script> 42 (function() { 43 var scale = 1, 44 $wrapper = document.getElementById(‘wrapper‘), 45 $body = document.getElementsByTagName(‘body‘)[0], 46 windowWidth = document.documentElement && document.documentElement.clientWidth || document.body.clientWidth || window.innerWidth, 47 windowHeight = document.documentElement && document.documentElement.clientHeight || documentElement.body.clientHeight || window.innerHeight, 48 deviceAgent = navigator.userAgent.toLowerCase(), 49 setScale = function(scales) { 50 if ($wrapper.style.zoom === undefined) { 51 $wrapper.style.margin = ‘0px‘; 52 $wrapper.style.transformOrigin = ‘top left‘; 53 $wrapper.style.transform = ‘scale(‘ + scales + ‘)‘; 54 $wrapper.style.MozTransformOrigin = ‘top left‘; 55 $wrapper.style.MozTransform = ‘scale(‘ + scales + ‘)‘; 56 } else { 57 $wrapper.style.zoom = scales; 58 } 59 $body.style.display = ‘block‘; 60 } 61 62 try { 63 if (deviceAgent.match(/(iphone|ipod|android|windows\s*phone|symbianos)/)) { 64 if (window.localStorage && window.localStorage.getItem(‘scale_jumei‘)) { 65 scale = window.localStorage.getItem(‘scale_jumei‘); 66 } else { 67 scale = parseFloat(windowWidth / 320); 68 if (windowHeight > windowWidth) { 69 window.localStorage && window.localStorage.setItem(‘scale_jumei‘, scale); 70 } 71 } 72 //微信2.3版本的處理(2.3版本有一個bug就是獲取寬度不准確) 73 if (deviceAgent.match(/android\s*2.3/) && deviceAgent.match(/micromessenger/)) { 74 scale = 1; 75 } 76 if ($wrapper) { 77 setScale(scale); 78 } 79 } 80 } catch (e) { 81 scale = parseFloat(windowWidth / 320); 82 if ($wrapper) { 83 setScale(scale); 84 } 85 } 86 })(); 87 </script> 88 </body> 89 </html>
上面代碼很簡單大家一看就懂。這種方式做一個簡單的頁面以及平時做些活動啥得是沒問題的。也不需要在算百分比是多少啦,直接寫死寬度320布局就好啦,先說一下我得布局方式,就是讓設計做640的圖片。然后我們布局按照320來做就好,圖標什么的讓設計出2x圖或者3x圖,也就是做2倍icon或者3倍icon。2倍的icon目前在6plus上面還是會有點虛得。所以可以選擇3倍的icon,畢竟圖標什么的也不是太大。說一下這種方法的缺點吧。缺點是有的瀏覽器不支持zoom屬性,例如火狐,那就只能用scale了。還有一個缺點就是在計算某些元素的高度什么需要一個縮放系數的問題。畢竟有縮放的東西在里面。當然坑還是有解決方案的,下面就說一下我的頂寬布局最終解決方案。
三、頂寬布局之最終解決方案
為了解決上面布局的坑,我就弄了一個終極的解決方案,這個方案目前肯定也有一定的坑,不過貌似不是很大,畢竟沒有太多的人反饋。上面的方案也用了很久,目前沒有特別大得問題,尤其是在我們app里面沒有出現過重大事故。
接着說一下最終方案,就是通過font-size縮放,這需要用到一個rem的尺寸,大家沒事網上一搜就知道了。這個1rem目前等於16px,那么我上面的320布局豈不是可以搭建成寬度為20rem的尺寸,然后我里面所有的元素都可以用rem來代替px。這樣我不就可以通過在html上font-size進行縮放了嘛,其實就是這樣做的就ok。這里有一個轉換,就是要把css里面的px按照1rem = 16px的規則都替換成rem。這樣就ok了。這個方案目前的缺點就是需要編譯一下css樣式和不允許你寫內聯樣式,不允許寫內聯樣式的主要原因是要不你html也得進行編譯替換拉。目前我們得解決方案是在開發的時候我們還是按照320的布局方案來走。等發布到線上的時候做一個整體的gulp構建px替換成rem。於似乎就解決了大部分得問題。目前這個解決方案對我來說還是比較理想的。可能某些地方還有問題。不過也算一種嘗試吧,有什么問題大家可以一起解決。好了上一個段代碼
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 5 <meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 6 <meta name="format-detection" content="telephone=no"/> 7 <title>GreatBoy</title> 8 <style> 9 /*-----css Reset end-----*/ 10 body,h1,h2,h3,h4,h5,h6,p,ul,ol,form{ 11 margin:0; 12 padding:0px; 13 } 14 html{ 15 display: none; 16 } 17 18 .nav img{ 19 width:10rem; 20 } 21 22 </style> 23 </head> 24 <body> 25 <div class="nav"><img src="http://p1.jmstatic.com/banner/75/mobile_app/24326_0.jpg"/></div> 26 <div id="container"> 27 <div id="user">用戶信息<span id="userinfo"></span></div> 28 </div> 29 <script> 30 (function(win) { 31 var doc = win.document, 32 scale = 16, 33 $body = doc.getElementsByTagName(‘body‘)[0], 34 $html = doc.getElementsByTagName(‘html‘)[0], 35 windowWidth = doc.documentElement && doc.documentElement.clientWidth || doc.body.clientWidth || win.innerWidth, 36 windowHeight = document.documentElement && document.documentElement.clientHeight || documentElement.body.clientHeight || window.innerHeight, 37 deviceAgent = navigator.userAgent.toLowerCase(); 38 if ( deviceAgent.match( /(iphone|ipod|ipad|android|windows\s*phone|symbianos)/ ) ) { 39 try{ 40 if ( window.localStorage && window.localStorage.getItem(‘scale_greatboy‘) ) { 41 scale = window.localStorage.getItem(‘scale_greatboy‘); 42 } else { 43 scale = parseFloat(windowWidth * 16 / 320); 44 if (windowHeight > windowWidth) { 45 window.localStorage && window.localStorage.setItem(‘scale_greatboy‘, scale); 46 } 47 } 48 }catch(e){ 49 50 } 51 if (deviceAgent.match(/android\s*2.3/) && deviceAgent.match(/micromessenger/)) { 52 scale = 16; 53 } 54 $html.style.fontSize = scale + ‘px‘; 55 $html.style.display = ‘block‘; 56 } else { 57 window.onresize = function(){ 58 windowWidth = doc.documentElement && doc.documentElement.clientWidth || doc.body.clientWidth || win.innerWidth; 59 scale = parseFloat(windowWidth * 16 / 320); 60 $html.style.fontSize = scale + ‘px‘; 61 }; 62 scale = parseFloat(windowWidth * 16 / 320); 63 $html.style.fontSize = scale + ‘px‘; 64 $html.style.display = ‘block‘; 65 } 66 $body.style.width = ‘20rem‘; 67 })(window); 68 </script> 69 </body> 70 </html>
總結一下,這個解決方案目前的缺點。1、css需要編譯。2、動態計算的時候一定不要把js里的高度寬什么的寫死,一定要動態獲取。3、在不支持rem的瀏覽器上會有問題。 目前這也是我想到的最好得解決方案,由於技術水平比較低哈哈。所以代碼質量不高,有什么問題大家可以一起交流討論,如果上面代碼大家有疑惑可以看一下線上的頁面原代碼,點擊這里,對啦看淘寶的源代碼,貌似淘寶的首頁是用fontsize縮放解決的。不過沒有看到他們是怎么計算的,有空研究一下。不過我覺得淘寶首頁這個自己實現的滾動條還是比較牛,至少在我們公司領導是不允許這么實現的,因為小米3的android機子看了一眼還是會卡頓。。。。太晚了,要去睡覺啦,如果有錯別字什么的大家見諒(語文功底比較差哈哈)。