移动端布局

Posted 开发的点点滴滴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移动端布局相关的知识,希望对你有一定的参考价值。

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 时==>
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

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 = {}));
View Code

 

$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;
}

以上是关于移动端布局的主要内容,如果未能解决你的问题,请参考以下文章

Flex布局详解

移动端适配(手机端rem布局详解)

总结个人使用过的移动端布局方法

总结个人使用过的移动端布局方法

Web移动端Fixed布局的解决方案

Web移动端Fixed布局的解决方案