前言
在移动端web开发上,不免会遇到各种移动设备的适配问题。在不断踩坑的路上,总结出了两套毕竟适合的适配移动端布局的方案。
方案一:媒体查询+viewport
描述:CSS3的媒体查询方案很大层度上已经帮我们完成了适配各种屏幕分辨率的问题。
1 @charset "utf-8"; 2 html,body{ 3 width: 100%; 4 height: 100%; 5 } 6 @media screen and (min-width: 320px) { 7 html { 8 font-size: 50px; 9 }10 }11 @media screen and (min-width: 360px) {12 html {13 font-size: 56px;14 }15 }16 17 @media screen and (min-width: 400px) {18 html {19 font-size: 63px;20 }21 }22 23 @media screen and (min-width: 440px) {24 html {25 font-size: 69px;26 }27 }28 29 @media screen and (min-width: 480px) {30 html {31 font-size: 75px;32 }33 }34 @media screen and (min-width: 640px) {35 html {36 font-size: 100px;37 }38 }39 body{40 font-family:'Microsoft YaHei',"Trebuchet MS",Verdana,Helvetica,Arial,sans-serif;41 font-size:0.28rem;42 color:#000000;43 background-color: #ffffff;44 }45 *{46 padding:0;47 margin:0;48 box-sizing: border-box;49 }50 ul,ol,ul li,ol li{51 list-style-type: none;52 }53 /*设置取消input默认样式*/54 input{55 -webkit-appearance: none;56 -moz-appearance: none;57 appearance: none;58 }59 /*设置input placeholder字体色号*/60 ::-webkit-input-placeholder {61 color: #767676;62 }63 :-moz-placeholder {64 color: #767676;65 }66 ::-moz-placeholder {67 color: #767676;68 }69 :-ms-input-placeholder {70 color: #767676;71 }72 input:focus::-webkit-input-placeholder{73 color:#767676;74 }75 /*设置清除浮动*/76 .clear:after{77 content: '';78 display: block;79 width:100%;80 height: 0;81 visibility: hidden;82 clear: both;83 }
再结合针对移动网页优化的viewport,即可完成大部分的移动端适配布局。
方案二:引入flexible
借鉴淘宝弹性布局方案flexible.js,即可完成移动端的布局。
代码出处:https://github.com/amfe/lib-flexible/blob/master/src/flexible.js
备注:直接引用时需要加js代码放置head头部内。
1 ;(function(win, lib) { 2 var doc = win.document; 3 var docEl = doc.documentElement; 4 var metaEl = doc.querySelector('meta[name="viewport"]'); 5 var flexibleEl = doc.querySelector('meta[name="flexible"]'); 6 var dpr = 0; 7 var scale = 0; 8 var tid; 9 var flexible = lib.flexible || (lib.flexible = {}); 10 11 if (metaEl) { 12 console.warn('将根据已有的meta标签来设置缩放比例'); 13 var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/); 14 if (match) { 15 scale = parseFloat(match[1]); 16 dpr = parseInt(1 / scale); 17 } 18 } else if (flexibleEl) { 19 var content = flexibleEl.getAttribute('content'); 20 if (content) { 21 var initialDpr = content.match(/initial\-dpr=([\d\.]+)/); 22 var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/); 23 if (initialDpr) { 24 dpr = parseFloat(initialDpr[1]); 25 scale = parseFloat((1 / dpr).toFixed(2)); 26 } 27 if (maximumDpr) { 28 dpr = parseFloat(maximumDpr[1]); 29 scale = parseFloat((1 / dpr).toFixed(2)); 30 } 31 } 32 } 33 34 if (!dpr && !scale) { 35 var isAndroid = win.navigator.appVersion.match(/android/gi); 36 var isIPhone = win.navigator.appVersion.match(/iphone/gi); 37 var isIPad = win.navigator.appVersion.match(/ipad/gi); 38 var devicePixelRatio = win.devicePixelRatio; 39 if (isIPhone) { 40 // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案 41 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { 42 dpr = 3; 43 } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ 44 dpr = 2; 45 } else { 46 dpr = 1; 47 } 48 } else { 49 // 其他设备下,仍旧使用1倍的方案 50 dpr = 2; 51 } 52 scale = 1 / dpr; 53 } 54 55 docEl.setAttribute('data-dpr', dpr); 56 if (!metaEl) { 57 metaEl = doc.createElement('meta'); 58 metaEl.setAttribute('name', 'viewport'); 59 metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); 60 if (docEl.firstElementChild) { 61 docEl.firstElementChild.appendChild(metaEl); 62 } else { 63 var wrap = doc.createElement('div'); 64 wrap.appendChild(metaEl); 65 doc.write(wrap.innerHTML); 66 } 67 } 68 function IsPC() 69 { 70 var userAgentInfo = navigator.userAgent; 71 var Agents = new Array("Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"); 72 var flag = true; 73 for (var v = 0; v < Agents.length; v++) { 74 if (userAgentInfo.indexOf(Agents[v]) > 0) { flag = false; break; } 75 } 76 return flag; 77 } 78 function refreshRem(){ 79 var width = docEl.getBoundingClientRect().width; 80 // if (width / dpr> 540) { 81 // width = 540 * dpr; 82 // } 83 if (IsPC() && width < 2047) { 84 width = 540; 85 } 86 87 var rem = width / 6.4; 88 docEl.style.fontSize = rem + 'px'; 89 flexible.rem = win.rem = rem; 90 } 91 92 win.addEventListener('resize', function() { 93 clearTimeout(tid); 94 tid = setTimeout(refreshRem, 300); 95 }, false); 96 win.addEventListener('pageshow', function(e) { 97 if (e.persisted) { 98 clearTimeout(tid); 99 tid = setTimeout(refreshRem, 300);100 }101 }, false);102 103 if (doc.readyState === 'complete') {104 doc.body.style.fontSize = 14 * dpr + 'px';105 } else {106 doc.addEventListener('DOMContentLoaded', function(e) {107 doc.body.style.fontSize = 14 * dpr + 'px';108 }, false);109 }110 111 112 refreshRem();113 114 flexible.dpr = win.dpr = dpr;115 flexible.refreshRem = refreshRem;116 flexible.rem2px = function(d) {117 var val = parseFloat(d) * this.rem;118 if (typeof d === 'string' && d.match(/rem$/)) {119 val += 'px';120 }121 return val;122 }123 flexible.px2rem = function(d) {124 var val = parseFloat(d) / this.rem;125 if (typeof d === 'string' && d.match(/px$/)) {126 val += 'rem';127 }128 return val;129 }130 })(window, window['lib'] || (window['lib'] = {}));
加载完毕后,页面根节点html会有个data-dpr属性(dpr:设备像素和CSS像素的比值)。通过
[data-dpr=‘x’]属性设置CSS样式就可以很好的解决了在高清屏幕下图片存在失真的问题。
总结
通过这两种方案,就可以很好的解决了移动端适配的问题。当然推荐引入flexible.js。