前言

移动端适配一直以来都是前端开发中不可或缺的重要组成部分,如果没有了它,那么你做出来的页面极有可能会出现各种意外(写出来的页面与设计稿之间的差别)。所有我们得找到一种相对来说让人比较满意的解决方案,尽可能地让这种“意外”减到最少。没错今天的主角就是它“flexible.js” 。

flexible.js 之旅

flexible.js 的作用就是让你在不同的终端设备之间如鱼得水,如入无人之境。说得那么浮,一点感觉都没有。不急,我们慢慢来,一步一步走进 flexible.js 神秘的世界。

flexible.js 有什么用

正如文章标题所写的那样,它就是一个终端设备适配的解决方案。也就是说它可以让你在不同的终端设备中实现页面适配。

flexible.js 怎么用

flexible.js 的用法非常的简单,在页面的<head></head>中引入 flexible_css.js,flexible.js文件:

外部引入
  1. // 加载阿里CDN的文件
  2. <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>

除了上面这种方式外,你还可以把这两个文件下载到自己的项目中,然后再引入,效果是一样的。

上面两个文件其实就是一个 .css 文件和一个 .js 文件:

.css 文件内容

    @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}

一看就知道这个 .css 文件是用来干嘛的了。

.js 文件内容
(function(win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {}); if (metaEl) {
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 = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute('data-dpr', dpr);
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
} refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
}
return val;
}
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
}
return val;
}
})(window, window['lib'] || (window['lib'] = {}));

不要觉得这个.js 文件的内容多,因为其核心代码也就十几二十行。其实上面两个文件的内容都基本都不需要怎么看,你只需要引入它们就好。

接下来你要做的就是在页面中使用这个解决方案给你提供套路。说真的套路其实就是以根节点为基准值,然后就没有然后了……,官方有这么一段话,你可以好好感受下:

提示

另外强烈建议对JS做内联处理,在所有资源加载之前执行这个JS。执行这个JS后,会在元素上增加一个data-dpr属性,以及一个font-size样式。JS会根据不同的设备添加不同的data-dpr值,比如说2或者3,同时会给html加上对应的font-size的值,比如说75px。 如此一来,页面中的元素,都可以通过rem单位来设置。他们会根据html元素的font-size值做相应的计算,从而实现屏幕的适配效果。

事实上 flexible.js 做了下面三件事:

  • 动态改写标签
  • 给<html>元素添加data-dpr属性,并且动态改写data-dpr的值
  • 给<html>元素添加font-size属性,并且动态改写font-size的值

官方粟子:

下图为一个简单得不能再简单的示意图(假装它是一个宽为 750px  的移动端设计稿):

图片虽然丑了一点,那能说明意思就足够了,请看左边的那几条红线以主旁边的标注。现在我们来假装要做一个页面(设计稿宽为 750px)。在这个例子中我们只是想说明如何使用flexible.js ,其它的暂时不考虑在内。在开始之前,我们还有必要研读下这句话:

提示

目前Flexible会将视觉稿分成**100份**(主要为了以后能更好的兼容vh和vw),而每一份被称为一个单位a。同时1rem单位被认定为10a。针对我们这份视觉稿可以计算出:

换算
  1. 1a = 7.5px
  2. 1rem = 75px

上面这一小段提示可以说是 flexible.js 的精华所在了。但你只需要记住1rem = 75px 就好。比如上面云库网这个 LOGO 距离左边60px,上边42px,图片自身宽、高都是80px。当然你也可以直接用这些数值:

传统做法
  1. .logo{
  2. width:80px;
  3. height:80px;
  4. margin-left:60px;
  5. margin-top:42px;
  6. }

但我们是要在移动端做适配的,这样写还有什么适配可言?我们可以把上面的像素转换成 rem。rem 是根据根元素(html 的字体大小)来进行计算的,这样就可以很方便地让我们把设计稿等比缩放到与实践终端相匹配的大小。

移动适配
  1. .logo{
  2. width: 1.066667rem;
  3. height: 1.066667rem;
  4. margin-left: 0.8rem;
  5. margin-top: 0.56rem;
  6. }

说得简单点就是 rem 相当于我们平常用的百分比,只不过 rem 是相对根元素的。而我们的根元素是根据终端屏幕大小来动态设置的,所以不管是 iphone 6 plus (尺寸为414*736)还是 iphone 6 (尺寸为375*667),或者是其它任何终端设备都可以很完美地还原设计稿。

还有一个关于 px 转 rem 的,你也不用自己一个一个手动去换算,这里有一个插件你可以安装下,它会自动地帮你把 px 换算成 rem 。

传送门:https://github.com/flashlizi/cssrem

安装方法也很简单:

  • 下载本项目,比如:git clone https://github.com/flashlizi/cssrem
  • 进入packages目录:Sublime Text -> Preferences -> Browse Packages…
  • 复制下载的cssrem目录到刚才的packges目录里。
  • 重启Sublime Text。

参数配置:

参数配置文件:Sublime Text -> Preferences -> Package Settings -> cssrem

  • px_to_rem – px转rem的单位比例,默认为40。
  • max_rem_fraction_length – px转rem的小数部分的最大长度。默认为6。
  • available_file_types – 启用此插件的文件类型。默认为:[“.css”, “.less”, “.sass”]。

这里有一个插件的效果图(来自官方):

简单、易用、你值得下载用一用!

参考资料

https://github.com/amfe/lib-flexible
https://github.com/flashlizi/cssrem

其它更多的详细内容,你可以到这两个网站中阅读,本文也只能送你到这里了。

移动端适配方案 flexible.js的更多相关文章

  1. 手淘移动适配方案flexible.js兼容bug处理

    什么是flexible.js 移动端自适应方案 https://www.jianshu.com/p/04efb4a1d2f8 什么是rem 这个单位代表根元素的 font-size 大小(例如 元素的 ...

  2. 手淘H5移动端适配方案flexible源码分析

    移动端适配一直是一个值得探讨的问题,在业余时间我找了一些页面,查看了一些厂商对于移动端H5页面的适配方案,看到了几个典型的例子,今天就来记录一下我看到的第一个典型的例子,也是我们公司目前普通H5项目正 ...

  3. 手淘的移动端适配方案flexible

    基于 vue-cli 配置手淘的 lib-flexible + rem,实现移动端自适应 安装 flexible npm install lib-flexible --save 引入 flexible ...

  4. 基于Vue/React项目的移动端适配方案

    本文的目标是通过下文介绍的适配方案,使用vue或react开发移动端及H5的时候,不需要再关心移动设备的大小,只需要按照固定设计稿的px值布局,提升开发效率. 下文给出了本人分别使用create-re ...

  5. rem移动端适配方案

    一. rem vs em 单位 定义 特点 rem font size of the root element 以根元素字体大小为基准 em font size of the element 以父元素 ...

  6. H5 APP 页面移动端适配方案

    H5 APP 页面移动端适配方案 https://segmentfault.com/a/1190000011586301 https://juejin.im/post/5cbdee71f265da03 ...

  7. 移动端自适应:flexible.js可伸缩布局使用

    http://caibaojian.com/flexible-js.html 阿里团队开源的一个库.flexible.js,主要是实现在各种不同的移动端界面实现一稿搞定所有的设备兼容自适应问题. 实现 ...

  8. 转载:移动端自适应:flexible.js可伸缩布局使用

    阿里团队开源的一个库.flexible.js,主要是实现在各种不同的移动端界面实现一稿搞定所有的设备兼容自适应问题. 实现方法: 通过JS来调整html的字体大小,而在页面中的制作稿则统一使用rem这 ...

  9. 移动端适配方案-rem(基础篇)

    常见移动web适配方案一般有3种方法,如下图: ①:定高,宽度百分比(一般用来做一些适配性不高的页面,比如主要以一些文字和图片为主的网页或移动端的头部和底部) ②:flex (更多的用于复杂页面的布局 ...

随机推荐

  1. Python-JS中的事件详解

    目录 fdf!! fefd 一.JS中的事件二.JS中的事件分类: 1.事件初级: 2.事件参数 Event 3.鼠标事件 4.键盘事件 *** 5.表单事件 *** 6.文档事件 * 7.图片事件 ...

  2. PYTHON-模块 logging hashlib

    '''import logging # 1. 控制日志级别# 2. 控制日志格式# 3. 控制输出的目标为文件logging.basicConfig(filename='access.log', fo ...

  3. 如何通过编译Linux内核打开IPVS(LVS)的debug模式

    前言 为了定位keepalived VIP的问题, 一步一步定位到IPVS, IPVS默认是没有打开Debug模式的, 若需要打开Debug模式需要重新编译IPVS模块加载后才行, 最好的方式当然是仅 ...

  4. html----常见的标签

    HTML标签: <strike>为文字加上一条中线</strike> <em>: 文字变成斜体.</em> 2<sup>2</sup& ...

  5. Myeclipse如何使用自带git工具向远程仓库提交代码

    先看一下Myeclipse自带的git工具  本人是在码云上面注册的账号,上面有项目的仓库,将仓库的项目克隆到本地之后,在myeclipse中导入该项目. 那么如何将修改后的代码再提交到码云上面? 第 ...

  6. Asp.Net构架(Http请求处理流程)、(Http Handler 介绍)、(HttpModule 介绍)

    Asp.Net构架(Http请求处理流程) Http请求处理流程概述 对于普通访问者来说,这就像每天太阳东边升起西边落下一样是理所当然的:对于很多程序员来说,认为这个与己无关,不过是系统管理员或者网管 ...

  7. Javascript事件设计模式(七)

    一:事件设计概述 事件机制可以使程序逻辑更加符合现实世界,在JavaScript中很多对象都有自己的事件,例如按钮就有onclick事件,下拉列表框就有 onchange事件,通过这些事件可以方便编程 ...

  8. CSS - !important声明强制优先

    !important声明强制优先 CSS优先级中还有一个最无敌的声明,就是!important. 在CSS样式表中,带有!important声明的样式优先使用,它的优先级会超越任何地方.任何方式的样式 ...

  9. JDK的get请求方式

    package com.example.wang.testapp3; import android.app.ProgressDialog; import android.os.Bundle; impo ...

  10. 【Java】 剑指offer(53-3) 数组中数值和下标相等的元素

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程 ...