移动端 flexible.js 布局详解

原本想直接引入原文链接,但是又担心作者哪天想不开注销账号,这么好的一篇文章看不到了,还是转载一下吧(/ω\)。
另外推荐一篇好文:移动端rem自适应实操讲解

本文讲的通过 flexible.js 实现了rem自适应,有了 flexible.js,我们就不必再为移动端各种设备兼容烦恼,flexible.js 是如何通过 rem 实现自适应的呢?一起来看看: 通过 rempx 的换算,你可以把设计稿从 px 转到 rem。再也不用为各种设备横行而担忧。

rem是相对于根元素 <html>,这样就意味着,我们只需要在根元素确定一个 px 字号,则可以来算出元素的宽高。1rem=16px(浏览器html的像素,可以设定这个基准值),假如浏览器的 html 设为 64px,则下面的元素则 1rem=64px 来运算。 阿里团队开源的一个库。使用 flexible.js 轻松搞定各种不同的移动端设备兼容自适应问题

实现方法

通过js来调整html的字体大小,而在页面中的制作稿则统一使用rem这个单位来制作。关键代码如下:

;(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'] = {}));

从上面的代码,主要是改变了 dpxdocumentfont-size 大小。大小为 docEl.getBoundingClientRect().width / 10 + 'px';, 假设我们的设计稿宽是 640 的,则 html 的字体大小则被设为 64px 。则相当于1rem=64px。 假如一个元素的宽是 160px ,在平时,我们可以采用百分比可以做到自适应,假如使用响应式的话,可能需要设置多个,比如在 320px,输出 80px,而在 640px 输出160px 等。 而采用以上 rem 的方法,则只需要输出 2.5rem 就能实现统一,如下表格:

设备宽度320px360px414px640px
Html字体大小32px36px41.4px64px
实际输出1rem1rem1rem1rem
设计稿缩放大小80px90px103.5px160px
实际输出2.5rem2.5rem2.5rem2.5rem

以上的 2.5rem 是怎么得出的呢? 160/64(1rem的基数为64px)=2.5rem ;按照官方的说法(640px举例) Flexible 会将视觉稿分成100份 (主要为了以后能更好的兼容 vhvw),而每一份被称为一个单位 a。同时 1rem 单位被认定为 10a。针对我们这份视觉稿可以计算出:(设计稿为 750px 为例)

1a   = 7.5px
1rem = 75px 

那么我们这个示例的稿子就分成了 10a,也就是整个宽度为 10rem<html> 对应的 font-size75px: 这样一来,对于视觉稿上的元素尺寸换算,只需要原始的 px 值除以 rem 基准值即可。例如此例视觉稿中的图片,其尺寸是 176px * 176px ,转换成为2.346667rem * 2.346667rem

本人理解:写移动端页面时,让设计人员将设计稿设计成宽为 640px,方便计算。因为当时的主流是iPhone5及iPhone5s,物理像素宽度为 640,分辨率为320。
在这里插入图片描述
如上图,当我们把分辨率调为 320 时,flexible.js 经过计算后,可以看到 <html>font-size 已经是 32 px了,也就是屏幕宽度 320 除以10的结果。
而此时设计稿是 640px 宽的,假设某个元素在设计稿上的宽为 128px,那么在实际开发中,我们要把它在 320px 的基础上计算,即开发时 128px/2/34px=2rem。
flexible分析,px转rem的插件工具

另外大漠还写了一篇详细的文章:使用 Flexible实现手淘H5页面的终端适配 里面介绍了一个如何快速转换rem为px的几种方法,感兴趣的童鞋可以去看看。 也可以看这篇文章:Sass函数功能——rem转px 另外在使用这个来处理自适应的另一个坑就是css sprite,作者的建议是使用svg,或者icon font.或者base64等其他方案。 另外就是在dpr=2时,小图片可能会出现模糊,建议以最大的图片来切图。



字体建议使用 px

在作者的观点中,是建议描述性的字体使用px,如果有slogan之类大于48px的,可以使用rem,由于使用rem在iPhone5和iPhone6中字体不同,可能出现13px和15px,点阵字体。 显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,所以我们不希望出现13px和15px这样的奇葩尺寸。 如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。

<style>
div { // 默认写上dpr为1的fontSizewidth: 1rem; height: 0.4rem;font-size: 12px;
}
[data-dpr="2"] div {font-size: 24px;
}
[data-dpr="3"] div {font-size: 36px;
}
</style>

为了能更好的利于开发,在实际开发中,我们可以定制一个font-dpr()这样的Sass混合宏:

<style>
@mixin font-dpr($font-size){font-size: $font-size;[data-dpr="2"] & {font-size: $font-size * 2;}[data-dpr="3"] & {font-size: $font-size * 3;}
}
</style>

有了这样的混合宏之后,在开发中可以直接这样使用:

@include font-dpr(16px);

当然这只是针对于描述性的文本,比如说段落文本。但有的时候文本的字号也需要分场景的,比如在项目中有一个slogan,业务方希望这个slogan能根据不同的终端适配。针对这样的场景,完全可以使用rem给slogan做计量单位。

由于使用 rem,要根据 rem 的数值来定,就像200*200,在分辨为 320px 下计算成 rem 后会出现小数,而对于字体来说当然不要有小数或者像 13px,15px 这种奇葩的字体,所以这里建议要么把字体 px 定死要么自己手写媒体查询吧。
如果你下载完看过源码,那你就知道,Flexible对屏幕的宽度做了一个小的限制,在你的屏幕宽度>540px的时候,<html>的 font-size 依然会是 54px,也就是当你把屏幕宽度设置为 640px 的时候,html 的 font-size 是 54px。
在这里插入图片描述
所以如果你想兼容更大尺寸的屏幕,那就把这段代码删掉好了。
图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gradle善良:获得更多的依赖性见解

在我们的大多数项目中&#xff0c;我们都依赖于其他代码&#xff0c;例如库或其他项目。 Gradle有一个不错的DSL来定义依赖关系。 依赖性在依赖性配置中分组。 这些配置可以自己创建&#xff0c;也可以通过插件添加。 一旦定义了依赖项&#xff0c;我们就可以通过dependencies任…

DotnetCharting控件的破解方法

在.net使用DotNetCharting控件生成报表统计图总结 文章中&#xff0c;不少博友提出“1.生成的图片带超链接导向官网,如何处理呀&#xff1f;2.我使用这个控件后&#xff0c;图形可以显示出来。但是发现一个小问题。就是在图形的左上方和图形的下面都隐含了超链接&#xff0c;鼠…

Android开发利器之ActivityTracker

版权声明&#xff1a;本文为xing_star原创文章&#xff0c;转载请注明出处&#xff01; 本文同步自http://javaexception.com/archives/113 Android开发利器之ActivityTracker 今天在群里面划水&#xff0c;有个小伙伴问到一个问题&#xff0c;”刚进公司 清单文件的activity 较…

js css模仿打字效果

1.效果 2.源码 <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <head><style type"text/css">#myDiv{display: inline-block;width:500px;height:300px;background-color:rgba(0,0,0,0.3);colo…

iframe 高度根据子页面来确定

标题描述一、解决方法解决代码二、关于高度问题简单讲一下jquery中的 height()&#xff0c;innerHeight()、outHeight()&#xff0c;js中的offsetHeight、clientHeight、scrollHeight。如何获取没有给出高度的元素的高度&#xff1f;详细介绍offsetHeight,clientHeight,scrollH…

避免许多if块进行验证检查

在某些情况下&#xff0c;我们需要先验证输入数据&#xff0c;然后再将其发送到业务逻辑层进行处理&#xff0c;计算等。这种验证在大多数情况下是孤立完成的&#xff0c;或者可能包括与外部数据或其他输入的某些交叉检查。 看下面的示例&#xff0c;该示例验证用户输入的注册数…

谷歌逐步取消对IE6的支持

1月30日&#xff0c;据国外媒体报道&#xff0c;谷歌周五宣布&#xff0c;截至3月1日&#xff0c;谷歌将不再其谷歌Docs和谷歌网站服务支持IE6。如果IE用户想使用那些产品&#xff0c;他们必须至少升级到版本7&#xff0c;如同“其他许多公司已经停止支持如Internet Explorer 6…

国内手机号正则表达式

java的写法&#xff1a; String pattern "^((1[358][0-9])|(14[57])|(17[0678])|(19[7]))\\d{8}$"; javascript的写法&#xff1a; var pattern /^((1[358][0-9])|(14[57])|(17[0678])|(19[7]))\d{8}$/; 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.co…

layui 子页面写弹出框覆盖父页面,以及给弹框中的表单赋值

咋说呢&#xff0c;因为对 layui 不太熟悉&#xff0c;这个弹出框搞了好久&#xff0c;看了好多解决方案&#xff0c;大致尝试了一下其中几种&#xff0c;在坑中无法自拔。。。总之终于搞出来了&#xff0c;在这里分享一下我的笔记。 着急的直接 戳这里 看解决代码。 尝试 1、…

html实现文字垂直居中且设置间隔

使用table和table-call布局 将表格作为一个table表&#xff0c;使用table-cell定义每个单元格的布局为table-cell, 抛出display的有效值 单元格中间的间隔使用 border-spacing:10px; border-collapse: separate;定义单元格vertical-align: middle; display: table-cell;代码源码…

入世与出世

同情恰好有两种。一种同情怯懦感伤&#xff0c;实际上只是心灵的焦灼。看到别人的不幸&#xff0c;急于尽快脱身出来&#xff0c;以免受到感动&#xff0c;陷入难堪的境地。这种同情根本不是对别人的痛苦抱有同感&#xff0c;而只是本能地予以抗拒&#xff0c;免得它触及自己的…

Hibernate隐藏的宝石:pooled-lo优化器

介绍 在这篇文章中&#xff0c;我们将揭示一个序列标识符生成器&#xff0c;​​它结合了标识符分配效率和与其他外部系统的互操作性&#xff08;同时访问底层数据库系统&#xff09;。 传统上&#xff0c;有两种序列标识符策略可供选择。 序列标识符&#xff0c;对于每个新值…

vue inheritAttrs、$attrs和$listeners使用

inheritAttrs、$attrs和$listeners使用场景&#xff1a; 组件传值&#xff0c;尤其是祖孙组件有跨度的传值。 &#xff08;1&#xff09;inheritAttrs 属性说明&#xff1a;https://cn.vuejs.org/v2/api/#inheritAttrs 说明比较晦涩。 组件传值一般是通过props传值的。inhe…

鼠标滚轮事件及解决滚轮事件多次触发问题

转载&#xff1a;https://www.cnblogs.com/jjxhp/p/11736066.html#_label0 一、滚轮事件的 js 写法 二、jQuery写法 三、参考 四、滚轮事件滚动过快&#xff0c;事件触发两次 一、js //判断鼠标滚轮滚动方向 if (window.addEventListener){ //FF,火狐浏览器会识别该方法wind…

Leetcode 2976. Minimum Cost to Convert String I

Leetcode 2976. Minimum Cost to Convert String I 1. 解题思路2. 代码实现 题目链接&#xff1a;2976. Minimum Cost to Convert String I 1. 解题思路 这道题思路上其实是非常直接的&#xff0c;本质上就是给出有向图之后&#xff0c;求出有向图上任意两点之间的最短距离&…

仍不切换到Java 8的6个理由

Java 8很棒。 期。 但是……在我们有机会玩耍并玩弄它之后&#xff0c;就该退出了&#xff0c;避免吃盐。 所有的好东西都是有代价的&#xff0c;在这篇文章中&#xff0c;我将分享Java 8的主要痛点。请确保在升级和放弃7之前您已经意识到了这些痛点。 1.并行流实际上会使您减…

硬币回收价格

1957年 1分 1元1960年 1分 80元 1962年 1分 30元1965年 1分 350元1966年 1分 180元1967年 1分 350元1968年 1分 88元1969年 1分 150元1977年 1分 320元1981年 1分 5元1988年 1分 300元1989年 1分 150元1990年 1分 180元1995年 1分 0.5元1955年 2分 15元1957年 2分 2元1958年 …

13 字符串相关函数

# ### 字符串相关函数 # *capitalize 字符串首字母大写 strvar "this is a dog" res strvar.capitalize() print(res)# *title 每个单词的首字母大写 (非字母隔开的单词) strvar "this is123a dog" res strvar.title() print(res)# *upper 将所有字母变…

Vue 生命周期LIFECYCLE是8个吗?

vue生命周期钩子个数是&#xff1a;11个。 export const LIFECYCLE_HOOKS [beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed,activated,deactivated,errorCaptured] github地址&#xff1a; https://github.com/vuejs/vue/blob/dev/…

鼠标滚轮切屏效果

某天发现一个网站《北京新鸿儒世纪网络技术有限公司》&#xff0c;一开始打开&#xff0c;哇&#xff0c;好简单啊&#xff0c;特别是首页&#xff0c;就一张图&#xff0c;后来发现里面有挺多小细节的&#xff0c;比如&#xff1a;做了媒体响应式、滚轮切屏&#xff08;第一次…