【移动端适配方案二 弹性布局】Flex弹性布局+rem实现移动端适配(JS+rem+viewport)
2018-06-26 13:42
941 查看
前端开发工程师根据UI设计师给的设计稿进行开发。
为了保证在各种屏幕上的不失真,就要根据实际屏幕宽度做等比例换算,才能写进CSS
实现如下:
1、设置width=device-width 也就是将layout viewport(布局视口)的宽度设置 为ideal viewport(理想视口)的宽度。
网页缩放比例为100%时,一个CSS像素就对应一个 dip(设备逻辑像素)
2、满足关系:
写入CSS的尺寸/屏幕宽度 = UI图标注的尺寸/UI图宽度
写入CSS的尺寸 = (UI图标注的尺寸*屏幕宽度)/UI图宽度
(由于设置了理想视口,所以视口宽度=屏幕宽度,这里在比值的时候就直接用屏幕宽度)
3、我们将根元素基准值设置为100px
为了保持设计稿中元素按比例还原,当屏幕尺寸变了,我们就要计算出变化的比例是多少。用屏幕尺寸/设计
稿尺寸得到缩放比例
缩放比例*基准值100px得到在这个屏幕尺寸下应该设置的font-size值也就是1rem的大小
如果屏幕320px,给的设计稿宽640px,那么这种情况下1rem就表示50px
要想做成响应式,只需要配合js动态获取视口宽度,再计算好对应屏幕下html font-size的值。
4、于是:写入CSS的尺寸 = UI图标注的尺寸/100px*1rem(注意,这里的1rem代表的值是html的font-size的大小,这个大小是随着屏幕尺寸变化而改变的)
document.documentElement.getBoundingClientRect().width
下面给出js更改html的font-size的代码,实际代码中就讲设计稿上的标注尺寸除以100单位改成rem就可以。
/* 设计稿的宽度:designWidth 允许自适应的最大宽度(超过这个值屏幕元素不在自适应增大):maxWidth 页面顶部加上:<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" > 这段js的传入两个参数:一个为设计稿实际宽度,一个为显示的最大宽度(允许的屏幕最大宽度,用来限制屏幕过大之后元素还会自适应增大的) 例如设计稿为750,最大宽度为600,则为(750,600),屏幕大于600之后就不会自适应变大了,也相当于在用@media属性时min-width只设置到了600,没有后面的屏幕尺寸,就不会再变化了 公式:1rem = 浏览器屏幕宽(width) * 100 / 设计稿宽(designWidth) (750,750)含义1rem = clientWidth * 100 / 750 (750,2160)含义1rem = clientWidth * 100 / 750 clientWidth是动态获取的 后面的750和2160表示maxWidth,如果浏览器窗口(clientWidth)大于这个数值就将clientWidth设置成这个数值(maxWidth)。而width是根据屏幕变化动态获取的 */ ;(function (designWidth, maxWidth) { var doc = document, win = window, docEl = doc.documentElement, remStyle = document.createElement("style"), tid; function refreshRem() { var clientWidth = docEl.getBoundingClientRect().width;//获取document的宽度,浏览器屏幕宽度 maxWidth = maxWidth || 540;//短路运算符,如果前面式子为false再执行后面,如果赋值了maxWidth那么maxWidth=maxWidth,否则没有赋值那么maxWidth为false,就会执行maxWidth=540 clientWidth > maxWidth && (clientWidth = maxWidth);//短路运算符,如果前面式子true再执行后面 var rem = clientWidth * 100 / designWidth; remStyle.innerHTML = 'html{font-size:' + rem + 'px;}'; } if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(remStyle); } else { var wrap = doc.createElement("div"); wrap.appendChild(remStyle); doc.write(wrap.innerHTML); wrap = null; } refreshRem(); //要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次; win.addEventListener("resize", function () { clearTimeout(tid); //防止执行两次 tid = setTimeout(refreshRem, 300); }, false); /* 浏览器后退的时候重新计算,为了查看页面是直接从服务器上载入还是从缓存中读取,你可以使用 PageTransitionEvent 对象的 persisted 属性来判断。 如果页面从浏览器的缓存中读取该属性返回 ture,否则返回 false */ win.addEventListener("pageshow", function (e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); /* 为什么一般多是 html{font-size:62.5%;} 而不是 html{font-size:10px;}呢? 因为有些浏览器默认的不是16px,或者用户修改了浏览器默认的字体大小(因浏览器分辨率大小,视力,习惯等因素)。 如果我们将其设置为10px,一定会影响在这些浏览器上的效果,所以最好用绝大多数用户默认的16作为基数 * 62.5% 得到我们需要的10px。 实际项目设置成 font-size: 62.5%可能会出现问题,因为chrome不支持小于12px的字体,计算小于12px的时候,会默认取12px去计算,导致chrome的em/rem计算不准确。 针对这个现象,可以尝试设置html字体为100px,body 修正为16px,这样 0.1rem 就是 10px,而body的字体仍然是默认大小,不影响未设置大小的元素的默认字体的大小。 */ if (doc.readyState === "complete") { doc.body.style.fontSize = "16px";//页面元素默认16px,如果不设置将是自动为16px显示 } else { doc.addEventListener("DOMContentLoaded", function (e) { doc.body.style.fontSize = "16px"; }, false); } })(750, 750);
rem方式的缺点:
dpr=1时没有任何问题,但是在dpr=2或者更高的手机屏幕上,因为物理像素的增加,存在小于1px的显示空间。如果采用第一种方法,因为它统一对scale设置为1,那么我们假如想要实现0.5px, 就只能通过transform的方式。
阅读更多
相关文章推荐
- 移动端rem布局中,当显示横屏时,解决根目录font-size切换屏幕不变情况(相较于引用rem.js方案的不足)
- js中flexible.js实现淘宝弹性布局方案
- js中flexible.js实现淘宝弹性布局方案
- 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)
- 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)
- js让你的rem弹性布局适配所有分辨率(含竖屏适配)
- js中flexible.js实现淘宝弹性布局方案
- 从零开始前端学习[39]:html5中的弹性布局二(移动端响应式实现各种布局,极其重要)
- 移动端rem适配(手淘flexible方案)
- js动态计算移动端rem(移动端适配rem)
- 使用 rem 实现 适配各种屏幕布局
- 移动端适配——rem方案
- rem自适应布局-移动端自适应必备:flexible.js
- 浅谈移动端的自适应问题——响应式、rem/em、利用Js动态实现移动端自适应
- 基于REM的移动端响应式适配方案
- 基于rem的移动端响应式适配方案(详解)
- 弹性盒子实现移动端的初始布局页面
- html移动端页面适配js(采用rem+百分比形式)
- 使用rem实现全屏幕自动适配(等比例缩放布局样式)
- vue使用rem实现 移动端屏幕适配