移动端布局
1.滚动条默认是在html上的,移到body上
html{ width: 100%; height: 100%; overflow: hidden; } body{ width: 100%; height: 100%; overflow: auto; }
2.高清屏1px边框还原
//因为像素比是放大的,缩放比可以缩小,只要相乘为1就能得到1px var pixelRatio = 1 / window.devicePixelRatio; //通过js动态设置视口的缩放比
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + pixelRatio + ', maximum-scale=' + pixelRatio + ', minimum-scale=' + pixelRatio + ', user-scalable=no');
// 在devicePixelRatio = 3 时==>
3.使用单位
px绝对单位,任何情况下都是固定值,在不同尺寸的屏幕下会错位。
% 相对单位,相对于父级(自身)的大小进行计算。对于不太好确定值的地方(如高度)不好使用百分比,会导致变形。
em相对单位,相对于当前字体大小的倍数。如果容器字体大小不一样,一一修改很麻烦。
rem 相对单位,只相对于html(root元素)的字体大小,移动端浏览器都兼容,这种布局比较通用。再在body里把font-size复原。
var html = document.getElementsByTagName('html')[0]; //屏幕宽度 var pageWidth = html.getBoundingClientRect().width; // 屏幕宽度 / 平分块数 = 基准值 html.style.fontSize = pageWidth / 16 + "px"; //然后计算容器的rem数值,这样不同的屏幕,容器布局结构不会变。(即将整个屏幕均等分,再计算各容器的占比。虽然屏幕大小不一样,但容器占屏幕的比例在各屏幕之间都一样) //开发css时,使用sass定义的函数,不用每次都用计算器计算:@include dpr(60px,height); //使用淘宝的flexible.js,给html元素增加[data-dpr='2']等属性,再结合scss的函数生成不同屏幕的css代码,完成移动端适配。
! function () { var innerStyle = "@charset \"utf-8\";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html {outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}", createStyle = document.createElement("style"); if (document.getElementsByTagName("head")[0].appendChild(createStyle), createStyle.styleSheet) createStyle.styleSheet.disabled || (createStyle.styleSheet.cssText = innerStyle); else try { createStyle.innerHTML = innerStyle; } catch (ex) { createStyle.innerText = innerStyle; } }(); // 淘宝移动端Flexible布局方案 ! function (window, nameSpace) { var timer, doc = window.document, docEl = doc.documentElement, // html元素 metaEl = doc.querySelector('meta[name="viewport"]'), flexibleEl = doc.querySelector('meta[name="flexible"]'), dpr = 0, scale = 0, Flexible = nameSpace.flexible || (nameSpace.flexible = {}); //刷新rem function refreshRem() { var width = docEl.getBoundingClientRect().width; width / dpr > 540 && (width = 540 * dpr); var rootSize = width / 10; docEl.style.fontSize = rootSize + "px", Flexible.rem = window.rem = rootSize; } if (metaEl) { //如果存在viewport meta标签,则使用里面的内容 console.warn('将根据已有的meta标签来设置缩放比例'); var match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } } else if (flexibleEl) { var content = flexibleEl.getAttribute('content'); if (content) { var initialDpr = content.match(/initial-dpr=([\d.]+)/); var maximumDpr = content.match(/maximum-dpr=([\d.]+)/); if (initialDpr) { dpr = parseFloat(initialDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximumDpr) { dpr = parseFloat(maximumDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } if (!dpr && !scale) { var isAndroid = window.navigator.appVersion.match(/android/gi); var isIPhone = window.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = window.devicePixelRatio; // 只对ios作了处理,android 采用1倍布局 if (isIPhone) { if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) { dpr = 2; } else { dpr = 1; } } else { dpr = 1; } scale = 1 / dpr; } if (docEl.setAttribute("data-dpr", dpr), !metaEl) if (metaEl = doc.createElement("meta"), metaEl.setAttribute("name", "viewport"), //j = scale //j = scale //j = scale metaEl.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no"), docEl.firstElementChild) docEl.firstElementChild.appendChild(metaEl); else { var createDiv = doc.createElement("div"); createDiv.appendChild(metaEl), doc.write(createDiv.innerHTML) } window.addEventListener("resize", function () { clearTimeout(timer), timer = setTimeout(refreshRem, 300); }, !1); window.addEventListener("pageshow", function (a) { a.persisted && (clearTimeout(timer), timer = setTimeout(refreshRem, 300)) }, !1); "complete" === doc.readyState ? doc.body.style.fontSize = 12 * dpr + "px" : doc.addEventListener("DOMContentLoaded", function () { doc.body.style.fontSize = 12 * dpr + "px" }, !1); refreshRem(); Flexible.dpr = window.dpr = dpr; Flexible.refreshRem = refreshRem; Flexible.rem2px = function (a) { var pxValue = parseFloat(a) * this.rem; return "string" == typeof a && a.match(/rem$/) && (pxValue += "px"), pxValue; }; Flexible.px2rem = function (a) { var remValue = parseFloat(a) / this.rem; return "string" == typeof a && a.match(/px$/) && (remValue += "rem"), remValue; } }(window, window.lib || (window.lib = {}));
$browser-default-font-size: 75px; // 根据dpr使用高清适配方案:适于需要写死尺寸的元素,如font-size
// 一套scss代码,生成适配3种dpr屏幕的css代码 @mixin dpr($size:$browser-default-font-size, $type:'font-size') { #{$type}: $size; [data-dpr="2"] & { #{$type}: $size*2; } [data-dpr="3"] & { #{$type}: $size*3; } } // px转rem:适于根据不同屏幕显示不同尺寸的元素,如div的width @function p2r($px, $base-font-size: $browser-default-font-size) { $value: $px / ($px*0+1); // 取无单位数值 $base-font-size: $base-font-size / ($base-font-size*0+1); // 取无单位数值 @return ($value / $base-font-size)* 1rem; }
4.使用背景图或者img,要针对不同的屏幕调整对应的大小:
如果图片大小和容器大小一致,可以使用width:100%。
如果图片和容器大小不一样,那么需针对图片分别设置宽/高,背景图设置background-size(x baseRem,y baseRem)。
在物理像素和css像素不是1:1时,retina屏相当于放大,会添加中间色的像素,导致模糊。想要图片不模糊失真,需要针对retina屏的图片重新制作一张像素总数更多的图片(2倍图@2x)。
5.文字要测量行高,再算padding(rem)
6.文字前插入小图标:
搜索框:div.search_box:before(图标)+form input(padding-left)
a标签:a的background(图标)+text-indent(文字)
7.<link rel='stylesheet'/>的媒体查询只是规定了复合条件的媒体样式表才会生效,但不符合条件的样式表依然会被下载到客户端。
8.移动端fixed定位的元素中有input时,触发键盘后会导致固定定位错位,可以使用绝对定位或者跳转到别的页面避免。
绝对定位会卡顿,需要用js解决,固定定位有兼容性问题
9.常用样式调整
a{ /*取消a标签手指按下时出现的黑色遮罩层*/ -webkit-tap-highlight-color:transparent; text-decoration:none; } input{ /*去除IOS下表单元素圆角*/ -webkit-apperance:none; }