Web移动端自适应布局之rem与高清屏下的矢量图使用

题图

24 Jun 2015

Author:wuguanxi


PART ONE -- rem


1、移动大潮下的屏幕碎片化


从2010年iphone4发布后这5年来,智能手机屏幕尺寸越来越大,规格也越来越多,单是苹果手机家族就4个尺寸,更不用提Android阵型了。

iphone

在Web移动端我们要使用视口(viewport)来控制浏览器的窗口在合适的大小内显示。我们这<head></head>里面加入关于视口的META标签


<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no,minimal-ui" />

加入视口标签后,手机浏览器会按照设备本身预先设定好的视口大小作为整个窗口的宽和高,不同手机的设置会不一样。

webview

如上图所视,移动端屏幕分辨率碎片化严重。


2、设计稿相关


面对多种不同的屏幕宽度,设计稿通常都只会设计一份,前端需要按照这份设计稿去适配不同设备。

公司的设计稿按照 640px × 1136px (I5/5s)给出,对应的5/5s在前端的实际显示应用应为320px(视口标签加入后),所以在前端布局上所有的尺寸都要除以2。


html{
    width: 100%;
    height: 100%;
    background-color: #fff;
  }
body{
  width:320px;
  font-size:16px;
  color:#000;
  background-color:tomato;
  margin:0 auto;   /* 水平居中 */
}
contrast1

因为浏览器最小能显示的中文字体字号是12px,所以要求设计稿中的中文字体字号最小是24px,而在考虑到移动端阅读的方便,正文一般是用16px,相应的设计稿正文为32px。


3、Web移动端自适应布局之rem


宽度320px的布局是完美适配I4/4s/I5/5s这类加入视口标签后宽度为320px的机型,但对其他机型需要进行一些处理。

处理的方法有很多,比如媒体查询法,百分比与flexbox结合大法,vw大法,还有就是rem大法。


今天只说rem。先说一下兼容性,我们祭出 caniuse.com

rem

如图可见,除了低版本IE傲娇外,在移动端是全面支持,可以大胆使用。那么,什么是rem?

Equal to the computed value of ‘font-size’ on the root element.

「rem」是指根元素(root element,html)的字体大小。那么除了html的字体大小不能用rem外,其他所有的css属性需要数值时都能用rem作为单位。这是极好的事情。


html{
  font-size:100px;
}
body{
  width:3.2rem;     /* 使用rem,宽为3.2 × 100px = 320px , 如果设计稿是750px就用 3.75rem */
  font-size:16px;
  color:#000;
  background-color:tomato;
  margin:0 auto;   /* 水平居中 */
}

于是对于不同宽的屏幕我们可以改变html的font-size大小,与320px一样的比例来达到适应的目的。屏幕的宽度用JS获取,然后剩下就是简单的比例运算。


//响应式设置(Zepto/JQ版)
$(document).ready(function(){                   //页面DOM加载完成时执行
  var $windowWidth = $(window).width();   //获得页面宽度
  setTimeout(function(){
    $windowWidth = $(window).width();
    $("html").css("font-size",(100/320) * $windowWidth + "px");  //改变html的字体大小
  },100);

  $(window).resize(function(){                //调试用
    $windowWidth = $(window).width();
    $("html").css("font-size",(100/320) * $windowWidth + "px");
  });
});
contrast2

ok,这样基本上就能全部响应了。

不过还有一个问题是,在PC端一般都是横屏看的话,会比较难看,于是我们在js上有一些小调整。


//响应式设置(Zepto/JQ版)
$(document).ready(function(){
  var $windowWidth = $(window).width();
  setTimeout(function(){
    $windowWidth = $(window).width();
    if($windowWidth > 640){
      $windowWidth = 640;               //限定最大宽度为640
    }
    $("html").css("font-size",(100/320) * $windowWidth + "px");
  },100);
  
  $(window).resize(function(){
    $windowWidth = $(window).width();
    if($windowWidth > 640){
      $windowWidth = 640;
    }
    $("html").css("font-size",(100/320) * $windowWidth + "px");
  });
});

// 优化后版本响应式设置(Zepto/JQ版)
$(document).ready(function(){                              //页面DOM加载完成时执行
  var $windowWidth = $(window).width();
  var $designWidth = $("body").attr("data-design-width");  //获得写在body的设计宽度 如果设计稿是750px就在 body上添加属性 data-design-width="750" 
  var $designdpr = $("body").attr("data-design-dpr");      //获得写在body的设计dpr
  $("html").attr("data-dpr",window.devicePixelRatio);      //获得设备dpr 写在 html 上
  if(!$designWidth){
    $designWidth = 640;                                    //没有获得 写在body的设计宽度 时,使用默认宽度 640px
  }
  if(!$designdpr){
    $designdpr = 2;                                        //没有获得 写在body的设计dpr 时,使用默认dpr 2
  }
  console.log($windowWidth,$designWidth,$designdpr);

  //下面都是换算 

  setTimeout(function(){
    $windowWidth = $(window).width();
    if($windowWidth > $designWidth){
      $windowWidth = $designWidth;
    }
    $("html").css("font-size",(100/($designWidth/$designdpr)) * $windowWidth + "px");
  },100);
  

  $(window).resize(function(){
    $windowWidth = $(window).width();
    if($windowWidth > $designWidth){
      $windowWidth = $designWidth;
    }
    $("html").css("font-size",(100/($designWidth/$designdpr)) * $windowWidth + "px");
  });
});

4、rem使用的地方


rem一般用在整体布局方面,局部的微调还是建议用px,如1px的边框,3px的圆角都不建议用rem


PART  TWO -- 矢量图在移动端的应用


1、矢量图?


矢量图(AI,PDF,EPS,SVG等)是区别于位图(JPG,PNG,GIF等)的一种图片格式,其特点是放大不会失真,在web上应用最广泛的是各种矢量字体和SVG。

本质上矢量图是运用数学描述图像的一种形式。


2、SVG


可缩放矢量图形(SVG)是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式。它由万维网联盟制定,是一个开放标准。

和HTML类似SVG也是XML的子集,而且SVG可以内嵌在HTML中,好处是可以进行通过JS对SVG进行DOM操作,下面是一个SVG文件,并通过<defs>和<use>重复使用。

<defs>是定义模版,<use>是重复使用。


<svg version="1.1" id="camera" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
  <defs>
    <g>
      <path fill="#003D99" d="M937.9,932.9H86.1C38.6,932.9,0,894.3,0,846.8V234.6c0-47.5,38.6-86.1,86.1-86.1h54.2l43.1-57.4h227.2
        l57.4,57.4h469.8c47.5,0,86.1,38.6,86.1,86.1v612.2C1024,894.3,985.4,932.9,937.9,932.9z M86.1,205.9c-15.8,0-28.7,12.9-28.7,28.7
        v612.2c0,15.8,12.9,28.7,28.7,28.7h851.7c15.8,0,28.7-12.9,28.7-28.7V234.6c0-15.8-12.9-28.7-28.7-28.7H444.3l-57.4-57.4H212.1
        l-43.1,57.4H86.1z"/>
    </g>
    <g>
      <path fill="#003D99" d="M512,741.7c-126.7,0-229.7-103-229.7-229.7s103-229.7,229.7-229.7s229.7,103,229.7,229.7
        S638.7,741.7,512,741.7z M512,339.7c-95,0-172.3,77.3-172.3,172.3S417,684.3,512,684.3S684.3,607,684.3,512S607,339.7,512,339.7z"
        />
    </g>
    <g>
      <circle fill="#003D99" cx="446.6" cy="441.9" r="35.1"/>
    </g>
  </defs>
</svg>

<div style="width:10px;">
  <svg version="1.1"  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
    <use xlink:href="#demo" />
  </svg>
</div>

<div style="width:40px;">
  <svg version="1.1"  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
    <use xlink:href="#demo" />
  </svg>
</div>

...

然后放在页面里

width:10px

width:40px

width:120px

width:200px

width:280px

与JS的交互(点它!)

SVG还有很多好棒的功能如SVGspriteSVG滤镜等等,但是。。。。

好用的技术不一定兼容,越好用的技术越不兼容。

----前端第一定律


3、SVG的兼容性


再次前往caniuse.com

基本上除了IE678和安卓3.0以下,其他的浏览器都支持SVG的一些基本功能,但其他如SVG滤镜等的高级属性在众多浏览器的表现并不一致。

于是在考虑到兼容性的场合下还是有其他选择的。


4、@font-face与字体图标


@font-face是一个CSS规则,允许你输入自己的字体出现在网站上,即使特定的字体在访问者的计算机上没有安装,而最重要的是连IE6都支持! 我们可以用矢量图生成字体,然后在网页里当成是文字来使用,也就是我们常说的字体图标。

强烈推荐下面的良心字体网站,https://icomoon.io/app/支持将上传的SVG转为字体文件,也支持生成SVGsprite。

即使是复杂的图案也能生成字体图标,而且作为字体能用CSS对其大小,颜色等属性进行操作和排版。