移动端适配flexible rem布局方案新手入门_rem攻略教程

如果你看了很多篇文章,对 flexible 的解决方案一直还有一种不太了解的朦胧感觉,那么这篇文章会帮你从背景角度一步一步解析为何会有 flexible 这套解决方案,以及这套解决方案是如何作用的。为什么不能直接用 px 进行布局设计师基于 iphone6(375px 逻辑像素) 的页面尺寸给了你一个非常简单的设计稿你很快用如下的代码实现了,在 chrome

移动端适配flexible rem布局方案新手入门

如果你看了很多篇文章,对 flexible 的解决方案一直还有一种不太了解的朦胧感觉,那么这篇文章会帮你从背景角度一步一步解析为何会有 flexible 这套解决方案,以及这套解决方案是如何作用的。

移动端适配flexible rem布局方案新手入门_rem攻略教程

为什么不能直接用 px 进行布局

设计师基于 iphone6(375px 逻辑像素) 的页面尺寸给了你一个非常简单的设计稿
移动端适配flexible rem布局方案新手入门_rem攻略教程

你很快用如下的代码实现了,在 chrome 控制台打开 iphone6 查看效果,和设计稿丝毫不差。

<div class="box1"></div>
<div class="box2"></div>
<style>
  .box1 {
    width: 100px;
    height: 100px;
    border: 1px solid red;
    position: fixed;
    left: 10px;
  }

  .box2 {
    width: 100px;
    height: 100px;
    border: 1px solid red;
    position: fixed;
    right: 10px;
  }
</style>

但是选则机型为 iphone5 时页面变成了这个样子。
移动端适配flexible rem布局方案新手入门_rem攻略教程
会发现在 iphone5 的页面下两个方块的间距和方块大小比起来变得非常小,这样我们认为这个网页在不同屏幕尺寸的手机上产生了不同的显示效果。
这个时候肯定有同学说了,那这个设计图我用 vw 去还原就好了。的确使用 vw 还原设计图是可以做到的,但 vw 目前的兼容性仍然有问题,测试很可能甩过来一个 vivo-x7 告诉你页面乱掉了。

Flexible 是如何解决以上问题的

设计师在 375px ( iphone6 逻辑像素宽度 ) 的页面上画出了这个设计图,则该 100px 的方块在不同尺寸的手机上的大小实际应该为 (100px/375px)*{屏幕逻辑像素宽度},然而我们不可能为每一种尺寸都在 css 上写一个 px 宽度。这时可以使用 rem,我们可以通过设置根节点的 font-size 来使不同尺寸的手机的 1rem 对应的 px 值不同。

上面的话读起来很绕,我写起来很绕,那么我将 100px 在 iphone5 和 iphone6 上的不同数值列个表

手机型号逻辑像素宽度根节点 font-sizerem 数值px 数值
iphone5320 px64 px(100/75) rem(100/75)*64 px
iphone6375 px75 px(100/75) rem(100/75)*75 px

这样在 iphone6 的屏幕尺寸上以 100px 渲染出来的盒子大小才能在 iphone5 的屏幕尺寸上以相同的比例渲染出来,在 iphone5 上渲染宽度为 (100/75)*64px == 85.33px,所以 flexible 的源码中refreshRem函数就是在计算不同手机尺寸应当设置的根节点 font-size,如下所示。

function refreshRem() {
  var width = docEl.getBoundingClientRect().width
  if (width / dpr > 540) {
    // 这里是为了适配 ipad 和 android 平板横屏的情况(请暂时无视这个 if 语句)
    width = 540 * dpr
  }
  var rem = width / 10 // 将屏幕宽度分为 10 份,每份为 1rem
  docEl.style.fontSize = rem + 'px'
  flexible.rem = win.rem = rem
}

著名的 1px 像素问题

如果读这篇文章同学在之前有读过其他地方的文章会认为我上面的解释是错误的,因为其他的文章在上面均使用的屏幕物理像素作为基准,并配合设置 <viewport content=”width=device-width,user-scalable=no,initial-scale=${scale}”> 实现,其实,如果没有 1px 像素的问题是不需要设置 initial-scale 的。在文章的前半部分着重讲解了如何用 rem 实现类似 vw 的效果,下面是关于 1px 像素问题的来龙去脉。

什么是 1px 像素问题

首先需要区分 物理像素 和 逻辑像素,物理像素即为显示器上的最小显示单元,逻辑像素也就是 css 像素,是在网页上渲染时的最小单位。而物理像素与逻辑像素之比 (物理像素/逻辑像素) 称之为 dpr (device pixel ratio),iphone 5的物理像素宽度为 640px,逻辑像素宽度为 320px,则 iphone5 的 dpr 为 2。意味着在 css 上写 1px 的宽度,在 iphone5 的显示屏幕上实际渲染了 2px 的物理像素,使得我们在 dpr>=2 的手机上设置 border-width:1px 看起来非常的粗。

如何解决 1px 像素问题

为了解决这个问题,flexible对上面的方案进行了优化。将 initial-scale 设置为 1/dpr,这样 dpr 为 2 的手机就会将页面缩小至 1/2 显示,这个时候设置 border-width:1px 就真的是 1px 物理像素。但是不能因为这个修改影响其他地方的布局,其实解决方案也很简单,就是将根节点的 font-size = font-size * dpr ,来将布局大小放大回正常的样子(但实际不是这样写的,是因为当设置了 scale = 1/2 时,documentn.documentElement.getBoundingClientRect().width 取得逻辑像素值会增大至 2 倍,所以不需要额外进行 根节点的 font-size = font-size * dpr)。

var width = docEl.getBoundingClientRect().width
var rem = width / 10 // 将屏幕宽度分为 10 份,每份为 1rem
docEl.style.fontSize = rem + 'px'

字体不能使用 rem,可能会出现小数

在 flexible 中有这样一行代码 docEl.setAttribute(‘data-dpr’, dpr);这样我们可以在自己的 css 中根据data-dpr来设置不同 dpr (可以理解为页面缩放比例) 下的字体大小

[data-dpr='1'] .text{
    font-size: 12px;
}
[data-dpr='2'] .text{
    font-size: 24px;
}
[data-dpr='3'] .text{
    font-size: 36px;
}

上面设计图的正确还原方式

在你的浏览器中打开这段代码并在移动端不同机型上进行切换,会得到正确的设计图还原效果。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script type="text/javascript" src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.2/??flexible_css.js,flexible.js">
  </script>
  <title>Document</title>
</head>

<body>
  <div class="box1"></div>
  <div class="box2"></div>
  <style>
    .box1 {
      width: 2.666666666666667rem; // 100px ÷ 37.5px(375px设计稿上的根 font-size 大小) = 2.666666666666667rem ,使用 css 预处理器的可以写一个函数
      height: 2.666666666666667rem;
      border: 1px solid red;
      position: fixed;
      left: 0.2666666666666667rem;
      top: 0.2666666666666667rem;
    }

    .box2 {
      width: 2.666666666666667rem;
      height: 2.666666666666667rem;
      border: 1px solid red;
      position: fixed;
      right: 0.2666666666666667rem;
      top: 0.2666666666666667rem;
    }
  </style>
</body>

</html>

Flexible 中源码的其他部分

希望看完这篇文章的你,再去这里再好好看一下源码的实现细节部分:flexible 源码

海计划公众号
(0)
上一篇 2020/03/24 05:37
下一篇 2020/03/24 05:37

您可能感兴趣的内容

  • laytpl小白帮助_轻量迷你的JavaScript模板解析

    laytpl小白帮助 官方网址:http://laytpl.layui.com/ GitHub:https://github.com/layui/laytpl 简介描述:轻量迷你的…

    2020/03/12
  • angular-cli入门攻略_快速构建Angular2项目

    angular-cli入门攻略 官方网址:https://cli.angular.io/ GitHub:https://github.com/angular/angular-cli…

    2020/03/06
  • JavaScript 的共享传递和按值传递入门指南_变量小白指南

    关于JavaScript如何将值传递给函数,在互联网上有很多误解和争论。大致认为,参数为原始数据类时使用按值传递,参数为数组、对象和函数等数据类型使用引用传递。按值传递 和 引用传递参数 主要区别简单可以说:按值传递:在函数里面改变传递的值不会影响到外面引用传递:在函数里面改变传递的值会影响到外面但答案是 JavaScript 对所有数据类型都使用按值传递。

    2020/03/30
  • Js通过.或者[]访问对象属性的语法、性能等区别入门教程_对象菜鸟教程网

    在JavaScript中可以使用 . 或者 [ ] 来访问对象的属性,但是对象中方法只能通过 . 来获取,例如:function Person() {this.name=” 张三 “; // 定义一个属性 namethis.say=function(){ // 定义一个方法say()return “我的名字是 ” + this.name ;}
    }
    var a

    2020/04/05
  • Kity Minder入门知识_百度脑图

    Kity Minder入门知识 官方网址:http://naotu.baidu.com GitHub:https://github.com/fex-team/kityminder …

    2020/03/06
  • 高级程序开发者有哪些特征?入门百科_程序入门基础

    开发人员的技能范围很广——资历往往不能决定一个人的能力。那么,是什么让一些人比他们的同龄人更优秀呢?是什么将他们与平庸的人群区分开来?拥有五年、十年甚至十五年的「工作经验」并不一定能保证你是一个高效的高级开发人员,甚至不一定会拥有这个头衔。当然,也有一些成功的高级开发,他们往往年纪更大,也不是很具有代表性。年轻的高级开发也不会到处都是,但高级开发人员有一些共

    2020/03/26
  • 微服务的定义、优缺点和最佳实践小白攻略_微服务小白知识

    回顾四五年前,围绕微服务架构的观点已经发生了很大的变化。首先,在看到 Netflix、亚马逊和 Gilt.com 等公司的成功故事后,开发人员认为微服务实际上是应用程序开发的一部分,这是炒作阶段。到现在为止,我们已经意识到微服务是另一种架构风格,当它以正确的方式应用于正确的问题时,会取得令人惊讶的成果,但它也有自己的优缺点。为了了解微服务到底是什么,什么时候

    2020/03/24
  • 理解大型分布式网站你必须知道这些概念使用帮助_网页作者: 转载菜鸟教程网

    1. I/O优化增加缓存,减少磁盘的访问次数。优化磁盘的管理系统,设计最优的磁盘方式策略,以及磁盘的寻址策略,这是在底层操作系统层面考虑的。设计合理的磁盘存储数据块,以及访问这些数据库的策略,这是在应用层面考虑的。例如,我们可以给存放的数据设计索引,通过寻址索引来加快和减少磁盘的访问量,还可以采用异步和非阻塞的方式加快磁盘的访问速度。应用合理的RAID策略提

    2020/04/05
  • Softonic教程视频_一个功能非常强大的软件下载网站

    Softonic教程视频 官方网址:https://en.softonic.com/ 简介描述:一个功能非常强大的软件下载网站 Softonic 是一个功能非常强大的软件下载网站,…

    2020/03/12
  • vue实现打印功能的两种方法基础教程_功能使用攻略

    第一种方法:通过npm 安装插件1,安装 npm install vue-print-nb –save2,引入安装好以后在main.js文件中引入 import Print from ‘vue-print-nb’
    Vue.use(Print); //注册3,现在就可以使用了

    明月照于山间

    清风来

    2020/03/30
  • 超实用的JQuery小技巧小白帮助_技巧菜鸟指南

    JQuery是一个 JavaScript 库,她极大的简化了我们对 JavaScript 的编程。今天我们总结了下平常项目中用到的一些小技巧,仅供参考。1、替换元素//替换元素
    $(document).ready(function(){$(“#id”).replaceWith(‘

    I have been repaced

    ‘)
    });2、延时加

    2020/03/29
  • JDC使用教程_注于电子商务视觉设计、交互设计、用户研究、前端开发

    JDC入门百科 官方网址:http://jdc.jd.com/ 简介描述:注于电子商务视觉设计、交互设计、用户研究、前端开发 京东用户体验设计部门,致力于创造更美好的电子商务购物体…

    2020/03/06
  • 被嫌弃的程序员的一生使用攻略_程序员基础知识入门

    本文转载于100offer公众号(ID:im100offer)。100offer是一个帮助高端人才找工作的平台,长期关注互联网行业动态与职业发展。 程序员从早前的一种职业发展至今,俨然已经成为大众眼中的「特殊物种」。关于程序员的调侃与段子也盛产于网络,常常引起全网围观。但是程序员说到底并不是「两耳不闻窗外事,一心只用敲代码」,他们也有生活和工作上的烦恼与曲

    2020/03/30
  • 在jQuery中使用自定义属性基础知识_jquery菜鸟教程下载

    在jquery中 自定义属性及值,默认以下都是在class=‘acitve‘对象中 进行自定义属性操作:1,自定义属性格式:data-xxxx2,获取该属性值: $(‘.active‘).data(‘xxxx‘) 获取属性值:data-xxxx的值3,设置该属性值: $(‘.active‘).data(‘xxxx‘,‘love‘) 设置属性: data-xx

    2020/03/23
  • js是面向对象还是基于对象?小白帮助_对象菜鸟指南

    以前感觉这两个在本质上没有什么区别,面向对象和基于对象都是对一个抽象的对象拥有一系列的行为和状态,本质都是对象层。拜读了winter老师的音频和文档,颇有收获。对象:一个可以触摸或者可以看见的东西;人的智力可以理解的东西;可以指导思考或行动(进行想象或施加动作)的东西。对象的特点:对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。对象有状态:对象

    2020/03/30
  • 理解Javascript的正则表达式菜鸟攻略_正则小白知识

    正文相信很多人第一次见到正则表达式的第一印象都是懵逼的,对新手而言一个正则表达式就是一串毫无意义的字符串,让人摸不着头脑。但正则表达式是个非常有用的特性,不管是Javascript、PHP、Java还是Python都有正则表达式。俨然正则表达式已经发展成了一门小语言。作为编程语言的一部分,它不想变量,函数,对象这种概念那么容易理解。很多人对于正则表达式的理解

    2020/03/20