前言

移动端适配一直以来都是前端开发中不可或缺的重要组成部分,如果没有了它,那么你做出来的页面极有可能会出现各种意外(写出来的页面与设计稿之间的差别)。所有我们得找到一种相对来说让人比较满意的解决方案,尽可能地让这种“意外”减到最少。没错今天的主角就是它“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. EntityFramework codefirst Enable-Migrations No context type was found in the assembly “MyApp.Web” error

    Enable-Migrations -Force -ContextTypeName "MyApp.Repository.DataContext" -ProjectName &quo ...

  2. 单元测试-代码覆盖率 EclEmma

    1. EclEmma的介绍 EclEmma是一个开源的软件测试工具,可以在编码过程中查看代码调用情况.也可以检测单覆盖率. 2. Eclipse下EclEmma安装 1. 选择Help->Ecl ...

  3. jq中Deferred对象的使用

    var d=$.Deferred(); //deferred下面的方法有: // ["resolve", "resolveWith", "reject ...

  4. java 动态代理(类型信息)

    代理是基本的设计模式之一它为你提供额外的或不同的操作,而插入的用来代替"实际"对象的对象. package typeinfo; //: typeinfo/SimpleProxyDe ...

  5. 格式化输出的方法:%、.format()、f

    a = '123'a1 = '456'a2 = '789' %占位符 text = "a=%s"%atext1 = "a=%s,a1=%s,a2=%s"%(a, ...

  6. PHP PC端微信扫码支付【模式二】详细教程-附带源码(转)

    博主写这破玩意儿的时候花了大概快两天时间才整体的弄懂逻辑,考虑了一下~还是把所有代码都放出来给大家~抱着开源大无私的精神!谁叫我擅长拍黄片呢?同时也感谢我刚入行时候那些无私帮过我的程序员们! 首先还是 ...

  7. struts2之OGNL和struts2标签库和ValueStack对象

    OGNL简介: (1)OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.  struts2框架默认就支持Ognl表达式语言(所以 ...

  8. Jquery监听AJAX请求

    .ajaxComplete() 当Ajax请求完成后注册一个回调函数.这是一个 AjaxEvent. .ajaxError() Ajax请求出错时注册一个回调处理函数,这是一个 Ajax Event. ...

  9. java面试题大全-基础方面 答案自己写

    Java基础方面: 1.作用域public,private,protected,以及不写时的区别 2.Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类, ...

  10. 010 处理模型数据(ModelAndView,Map Model,@SessionAttributes)

    1.处理数据模型 SpringMVC提供了几种途径出书模型数据 二:ModelAndView 1.介绍 2.index <%@ page language="java" co ...