前言

移动端适配一直以来都是前端开发中不可或缺的重要组成部分,如果没有了它,那么你做出来的页面极有可能会出现各种意外(写出来的页面与设计稿之间的差别)。所有我们得找到一种相对来说让人比较满意的解决方案,尽可能地让这种“意外”减到最少。没错今天的主角就是它“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. Spring Boot学习笔记 - 整合Swagger2自动生成RESTful API文档

    1.添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!--swagger2--> <dependency> <groupId>io.spr ...

  2. 解析神奇的 Object.defineProperty

    这个方法了不起啊..vue.js是通过它实现双向绑定的..而且Object.observe也被草案发起人撤回了..所以defineProperty更有必要了解一下了. 几行代码看他怎么用 var a= ...

  3. python+selenium十二:一个输入框双层input标签

    先点击第一个,再对第二个进行操作,否则操作失败 driver.find_element_by_css_selector(".pwd").click()driver.find_ele ...

  4. 实现数据导出为.csv表格

    数据导出实现步骤: 1.查找出要导出的数据,整理为二维数组. 2.定义导出表格的字段 3.将整理的二维数组按导出表格定义的字段重新整理. 4.将整理的二维数组写入服务器中已有的一个.csv文件. 5. ...

  5. HDU 4763 求最大长度的串A,使得S满足APAQA

    给一个串,让你找一个子串,形如EAEBE,就是一个串在开头结尾中间各出现一次,问这个E最长是多少 Sample Input5xyabcaaaaaaabaaaxoaaaaa Sample Output0 ...

  6. [转] react-router4 实现按需加载

    按需加载的背景 https://juejin.im/post/58f9717e44d9040069d06cd6?utm_source=tuicool&utm_medium=referral R ...

  7. vtiger二次开发

    搞了快两个星期的vtiger,慢慢的摸索到了一些东西 数据库相当的复杂,已有的模块我只是分析了下页面的加载,方法的调用 大部分时间在研究怎么添加新的功能模块,今天才知道模块可以通过输入命令的方式来添加 ...

  8. SVN提交,提示“remains in conflict”错误

    SVN commit时,提示"remains in conflict"错误: 1.error出现原因: 在本地项目删除了一个目录,又通过SVN的"Repo-browser ...

  9. Python字符串capitalize center 方法

    一.capitalize 首字母大写 name = "wohaoshuai" print(name.capitalize()) #首字母大写 Wohaoshuai 二.center ...

  10. Matrix Power Series POJ3233

    递推思想  先放着 见 https://www.cnblogs.com/jackge/p/3147604.html