等比缩放布局(rem布局)的实现

  rem的定义,the font size of the root element,即以根节点的字体大小作为基准值进行长度计算。网页中的根元素指的是html我们通过设置html的字体大小就可以控制rem的大小。

  视口(viewport)设置:<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />

  在html上根据不同分辨率设置不停font-size,通过js计算出来。

  页面里除了font-size之外的其他css尺寸都使用了rem作为单位。

  正文的font-size需要额外的媒介查询,并且不使用rem。

  要搞懂移动端的适配,首先要高明白像素和视口。

  其实存在两种像素:

  1. 设备像素

  屏幕的物理像素,任何设备屏幕的物理像素的数量都是固定不变的,单位是pt

  2. CSS像素

  在CSS、JS中使用的一个抽象的概念,单位是 px

顺便说下,CSS像素也可以称为设备独立像素(device-independent pixels),简称为dips,单位是dp

  那么,我们现在再来说说一个元素 200px 。这个元素跨越了200个CSS像素,200个CSS像素相当于多少个设备像素取决于两个条件:

  • 页面是否缩放
  • 屏幕是否为高密度

  

  先梳理一下手机硬件之间的关系,注意这里使用的都是物理像素。

  以 iPhone5 为例,我们已知的是:

  1. 分辨率:1136pt x 640pt
    指屏幕上垂直有 1136 个物理像素,水平有 640 个物理像素
  2. 屏幕尺寸: 4英寸
    注意英寸是长度单位,不是面积单位。4英寸指的是屏幕对角线的长度。
  3. 屏幕像素密度:326dpi
    屏幕像素密度(Pibel Per Inch)简称 ppi ,单位是 dpi(dot per inch)。这里指屏幕水平或垂直每英寸有326个物理像素。原则上来说,ppi越高越好,因为图像会更加细腻清晰。

  ppi 是可以通过 分辨率 和 屏幕尺寸 计算得到的:ppi

  视口

  桌面浏览器中,浏览器窗口就是约束你的CSS布局视口(又称初始包含块)。它是所有CSS百分比宽度推算的根源,它的作用是给CSS布局限制了一个最大宽度,视口的宽度和浏览器窗口宽度一致。

  但是在移动端,情况就很复杂了。

  布局视口

  一个没有为移动端做优化的网页,会尽可能缩小网页让用户看到所有东西。

  浏览器厂商为了让用户在小屏幕下网页也能够显示地很好,所以把视口宽度设置地很大,一般在 768px ~ 1024px 之间,最常见的宽度是 980px。

  所以,在手机上,视口与移动端浏览器屏幕宽度不再相关联,是完全独立的,这个浏览器厂商定的视口被称为布局视口。

  布局视口我们是看不见的,只知道网页的最大宽度是 980px ,并且被缩放在了屏幕内。

  可以这样设置布局视口的宽度:<meta name="viewport" content="width=640">

  媒体查询与布局视口

  700px 指的是布局视口的宽度

  @media (min- 700px){
      ...
  }
  document.documentElement.clientWidth/Height返回布局视口的尺寸

  视觉视口

  视觉视口是用户正在看到的网页的区域,大小是屏幕中CSS像素的数量。

  window.innerWidth/Height返回视觉视口的尺寸

  理想视口

  布局视口明显对用户是不友好的,完全忽略了手机本身的尺寸。所以苹果引入了理想视口的概念,它是对设备来说最理想的布局视口尺寸。理想视口中的网页用户最理想的宽度,用户进入页面的时候不需要缩放。

  现在讨论所谓的『最理想的宽度』到底是多少?其实,如果我们把布局视口的宽度改成屏幕的宽度不就不用缩放了么。可以这样设置告诉浏览器使用它的理想视口:

  <meta name="viewport" content="width=device-width">

定义理想视口是浏览器的事情,并不能简单地认为是开发者定义的,开发者只能使用。

  screen.width/height返回理想视口的尺寸,有严重的兼容性问题---可能返回两种值:

  1. 理想视口的尺寸(下载浏览器)
  2. 屏幕的设备像素尺寸(内置浏览器)
  缩放

  缩放与设备像素、CSS像素的关系

    缩放是在放大或缩小CSS像素,比如一个宽度为 200px 的元素放大,还是200个CSS像素。但是因为这些CSS像素被放大了,所以CSS像素也就跨越了更多的设备像素。缩小则相反。

   缩放与视口

  缩放会影响视觉视口的尺寸

  页面被用户放大,视觉视口内CSS像素数量减少;被用户缩小,视觉视口内CSS像素数量增多就行了。这个道理应该是不难想的。

  

用户缩放不会影响布局视口

注意,这是『用户缩放』,后面会说开发者设置缩放的情况

缩放比例

我们在开发者工具中可以在这里查看缩放比例:

查看缩放比例

这里的 0.3 是相对于理想视口的。

在下载浏览器中,可以这么算(理想视口与视觉视口的比):

zoom level = screen.width / window.innerWidth

禁止缩放

<meta name="viewport" content="user-scalable=no">

 

设置缩放

<meta name="viewport" content="initial-scale=2">

使用initial-scale有一个副作用:同时也会将布局视口的尺寸设置为缩放后的尺寸。所以initial-scale=1width=device-width的效果是一样的。

完美视口

解决各种浏览器兼容问题的理想视口设置

<meta name="viewport" content="width=device-width,initial-scale=1">

   

设备像素比

在谈到像素的时候,讲到除了缩放,屏幕是否为高密度也会影响设备像素和CSS像素的关系。

在缩放程度为100%(这个条件很重要,因为缩放也会影响他们)时,他们的比例叫做设备像素比(device pixel ratio):

dpr = 设备像素 / CSS像素

可以通过JS得到: window.devicePixelRatio

设备像素比也和视口有关:

dpr = 屏幕横向设备像素 / 理想视口的宽

总结

这一篇介绍了移动端适配需要掌握的知识,先说明了移动端存在的两种像素,然后介绍了三种视口,由缩放对视口的影响引入理想视口,最后说明设备想告诉比。

 之前做过PC页面的人聊的最多的就是『兼容』,这是因为浏览器之间的差异引起的,不再多说。而移动端是基本没有『兼容』的问题的,全是CSS3,简直不要太开心。可是『适配』问题随之而来。

什么是『适配』?做PC页面的时候,我们按照设计图的尺寸来就好,这个侧边栏200px,那个按钮50px的。可是,当我们开始做移动端页面的时候,设计师给了一份宽度为640px的设计图。那么,我们把这份设计图实现在各个手机上的过程就是『适配』。

那么,我们怎么开始呢?目前有三种方法:

  • 固定高度,宽度自适应
  • 固定宽度,viewport缩放
  • rem做宽度,viewport缩放

这三种方法的核心都是视口的确定,现在以实现这个设计图为例说明。

固定高度,宽度自适应

demo

这也是目前使用最多的方法,垂直方向用定值,水平方向用百分比、定值、flex都行。腾讯京东百度天猫亚马逊的首页都是使用的这种方法。

随着屏幕宽度变化,页面也会跟着变化,效果就和PC页面的流体布局差不多,在哪个宽度需要调整的时候使用_响应式布局_调调就行(比如网易新闻),这样就实现了『适配』。

 

原理

这种方法使用了完美视口:

<meta name="viewport" content="width=device-width,initial-scale=1">

这样设置之后,我们就可以不用管手机屏幕的尺寸进行开发了。

固定宽度,viewport缩放

demo

设计图、页面宽度、viewport width使用一个宽度,浏览器帮我们完成缩放。单位使用px即可。

目前已知荔枝FM网易新闻在使用这种方法。有兴趣的同学可以看看是怎么做的。

 

原理

这种方法需要根据屏幕宽度来动态生成viewport,生成的 viewport 基本是这样:

<meta name="viewport" content="width=640,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">

640 是我们根据设计图定下的,0.5 是根据屏幕宽度动态生成的。

生成的viewport告诉浏览器网页的布局视口使用 640px,然后把页面缩放成50%,这是绝对的等比例缩放。图片、文字等等所有元素都被缩放在手机屏幕中。

这个gif图说明了一切:

1

rem做宽度,viewport缩放

demo

这也是淘宝使用的方案,根据屏幕宽度设定 rem 值,需要适配的元素都使用 rem 为单位,不需要适配的元素还是使用 px 为单位。

具体使用方法见使用Flexible实现手淘H5页面的终端适配

上文提供了sass和postcss的px2rem转换方法,我这里给出less的px2rem。因为less不支持函数,所以需要安装插件 less-plugin-functions ,然后就简单了:

.function{
    .px2rem(@px,@base:72px){
        return: @px / @base * 1rem;
    }    
}

这样使用:

div{
     px2rem(100px);
}

使用这个方法的库:

 

原理

实际上做了这几件事情:

  1. 动态生成 viewport
  2. 屏幕宽度设置 rem的大小,即给<html>设置font-size
  3. 根据设备像素比(window.devicePixelRatio)给<html>设置data-dpr

rem

这么设置的好处是可以让不同设备的rempx都显示一样的长度。

设置rem

设置rem的意义在于得到一个与屏幕宽度相关的单位,本来vw是最合适的,但是因为兼容性的问题,只能使用rem来做。这样,让不同设备的rem显示一样的长度。

vw是CSS3引入的单位,1vw = 1%窗口宽度

rem

上面的布局我们可以这样:

html{
    font-size: 屏幕宽度 / 10; 
}
.btn{
    8.75rem;
    height:1.25rem;
}

这样,无论屏幕宽度是多少,.btn都是相对于屏幕的这么宽,做到了适配。

设置 viewport 缩放 和 data-dpr

这两个设置其实是干的一件事,就是适配高密度屏幕手机的px单位。

.a{
  font-size:12px;
}
[data-dpr="2"] .a{
  font-size: 24px;
}
[data-dpr="3"] .a{
  font-size: 36px;
}

而缩放是动态的,这样,不同设备下的px显示一样的长度。

之前说过CSS像素和物理像素与缩放、dpr都有关系,这里说明:

在普通手机上,.a字体设置为12px;

在dpr是2的手机上,[data-dpr="2"] .a字体为24px,又因为页面缩放50%,字体为还是12px

总结

坦白说,我不觉得第一种方案能就做『适配』方案,因为太笨了,只能做一些列表等简单排列的样式

  

原文地址:https://www.cnblogs.com/JinQingsong/p/6613848.html