移动端布局方案 rem 示例
[ 方法1 ]
- 在谷歌浏览器中,打开任意模仿IPHONE的设备尺寸,查看body的宽度
- 将如下JS代码中pageW设置为上一步骤body的layout渲染宽度布
- 将PSD等比缩放/拉伸到改尺寸
- 安装PSD中尺寸正常测量布局px宽度, 并且在后续,将测量PX转化为REM,比例为 100px = 1rem
- 注意添加meta标签,对缩放禁止
(function (doc, win) {
var pageW = 980;
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if(clientWidth>=pageW){
docEl.style.fontSize = '100px';
}else{
docEl.style.fontSize = 100 * (clientWidth / pageW) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="user-scalable=no">
<script>
(function (doc, win) {
var pageW = 980;
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if(clientWidth>=pageW){
docEl.style.fontSize = '100px';
}else{
docEl.style.fontSize = 100 * (clientWidth / pageW) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</script>
/*你引进的资源*/
<title>标题</title>
</head>
<body>
/*你的代码*/
</body>
</html>
[ 方法2 ] - 网络参照 [ 小米官网 ]
- i的参数设置为PSD设计稿实际尺寸,如下面例子中,PSD设计稿假设为720
- 正常测量PX,然后按照100px = 1rem的比例计算
- 因为设置了meta的 width=device-width 所以不用考虑其他因素了
代码:
!function(n){
var e=n.document,
t=e.documentElement,
i=720,
d=i/100,
o="orientationchange"in n?"orientationchange":"resize",
a=function(){
var n=t.clientWidth||320;
if(n>720){ n=720 };
t.style.fontSize=n/d+"px"
};
e.addEventListener&&(n.addEventListener(o,a,!1),e.addEventListener("DOMContentLoaded",a,!1))
}(window);
模板[ REM ]
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<script>
//小米官网的写法
!function(n){
var e=n.document,
t=e.documentElement,
i=720,
d=i/100,
o="orientationchange"in n?"orientationchange":"resize",
a=function(){
var n=t.clientWidth||320;
if(n>720){ n=720 };
t.style.fontSize=n/d+"px"
};
e.addEventListener&&(n.addEventListener(o,a,!1),e.addEventListener("DOMContentLoaded",a,!1))
}(window);
</script>
<style>
body { margin:0;}
.wrap{position:absolute;top:0;left:0;bottom:0;right:0;background:#fefefe;}
.title{width:100%;height:0.98rem;line-height:0.98rem;color:#fff;background:#e02222;text-align: center;font-size:0.32rem;}
</style>
</head>
<body>
<div class="wrap">
<div class="title">首页</div>
</div>
</body>
</html>
[ 方法三]
- js会动态添加meta,以及html的font-size,并且改变他们在不同设备下的数值
- 需要借助谷歌浏览器模拟任意iphone尺寸设备,测量body的宽度,
- 将PSD设计稿等比调整至改值
例:如下
在IPHONEX设备模拟下,body宽度为1125,将其分为45份,每份为25,则该尺寸下html的font-size为25
当然为了方便计算,可以将此数值改为 11.25份,每份为100,则该尺寸下html的font-size为100
;(function(){
function setViewport(){
//获取像素比 - window.devicePixelRatio
var dpr = 1 / window.devicePixelRatio;
if(!document.getElementById('viewPortMeta')){
var oMeta = document.createElement('meta');
oMeta.name = "viewport";
oMeta.id = "viewPortMeta";
oMeta.content = "width=device-width,user-scalable=no,initial-scale="+dpr+",minimum-scale="+dpr+",maximum-scale="+dpr;
document.getElementsByTagName('head')[0].appendChild(oMeta);
}
var fz = document.documentElement.clientWidth / 45;
/*25*/
document.getElementsByTagName('html')[0].style.fontSize = fz + 'px';
}
setViewport();
//resize
if(window.orientation){
window.addEventListener('orientationchange',function(){
setViewport();
},false);
}else{
window.addEventListener('resize',function(){
setViewport();
},false);
}
})();
模板中
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>标题</title>
</head>
<body>
正文
</body>
</html>
<script type="text/javascript" src="js/viewport.js"></script>
区别优劣?
上面2个方法,
- 方法一,借助浏览器模拟IPHONE任意设备宽度,测量BODY渲染宽度,将PSD设计稿等比拉为此宽度,并且将JS中pageW修改为该值; 换算 [ 100px = 1rem ]
【注】: 微信浏览器 部分标签因为结构嵌套过于靠外,dom load 第一次渲染错误,orientationchange 触发会正常
可以修改结构,靠外元素需要单独嵌套1层,另外,最外面盒子需要添加rem为单位的宽度
方法二,只需要考虑设计稿,根据设计稿宽度设置脚本参数,HTML的 head中添加一段默认meta设置; 换算 [ 100px = 1rem ]
方法三,借助浏览器模拟IPHONE任意设备宽度,测量BODY渲染宽度,将PSD设计稿等比拉为此宽度,人为设置HTML划分多少份,计算html的font-size值以便后续计算;
如上例子中,1125宽度,45份,每份为25 ,则换算 需要根据实际情况 [ 25px = 1rem ]
【注】:部分安卓机器需要测试兼容性
法1会好一些,方便计算
- 将chrome切换移动端任意尺寸手机型号,查看computed的body宽度,
- 将PSD等比调整至此宽度,
- 将JS脚本中的pageW参数设置为改尺寸宽度,
- 最后进行切图,以及PX和REM转换
- 添加禁止缩放
<meta name="viewport" content="user-scalable=no">
方法1存在的问题
渲染问题,页面加载后有一个变化的过程,目力可见,不友好
解决方法:
- 将改变font-size脚本提到head标签内,在读取页面结构中,提前计算字体大小
- 将body隐藏,计算完font-size后,再显示body,使用visibility来做这个隐藏操作
- 行内块级元素,上下有空白高度,设置这个容器 font-size为0即可
- 在chrome模拟器上看没问题,真机出现字体首次渲染不到位,但是通过渲染手机横屏触发了二次渲染正常的话,需要在这个首次渲染问题的标签父级,增加font-size:0 即可
- 通过rem方式来布局,body上面必须要设置一个font-size, 例如: font-size:14px;或font-size:16px; 当然也可以使用rem
B站 的移动端布局方案
传统html设置字体,通过rem调整页面layout尺寸
var docEl = document.documentElement;
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
var visibleRatio = 0.72;
//设置html标签字体
var recalc = function () {
var clientWidth = docEl.clientWidth;
var clientHeight = docEl.clientHeight;
if (!clientWidth) {
return;
};
if (clientWidth >= 750) {
if (clientWidth / clientHeight < visibleRatio) {
docEl.style.fontSize = '100px';
} else {
//宽度大于750且宽高比大于0.72,那么让宽度等于高度的0.72
var w = visibleRatio * clientHeight;
docEl.style.fontSize = 100 * (w / 750) + 'px';
}
}else {
//常规移动端,html字号 750宽 = 100px ,适配设备的宽*100/750 = 当前字号
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
window.addEventListener(resizeEvt, recalc, false);
document.addEventListener('DOMContentLoaded', recalc, false);
[ 最简洁方案VW布局]
- 节省了常规通过计算视窗变化,重新计算HTML上font-size设置值的过程,一劳永逸
直接设置 html { font-size:26.6667vw; }
26.6667的由来,iPhone6\7\8 宽度为375px 一屏幕宽为100vw,如果求1px等于多少vw
便可以计算得知 1px100vw/375px = 0.266667vw ;
那么如果设置字体大小为100px = 1000.266667vw = 26.6667vw
而在iPhone6plus/7plus/8plus/时候,宽度为414px 乘以0.26667vw 可得110px,这与iphone6/7/8的100px 是等比变化的
如:
375/414 = 100/110 ; 这样就做到了vw一劳永逸的目的 - 将PSD调整为375进行PX布局,通过VsCode插件 px2rem配置基础font-size为100
圈选px样式部分,通过快捷键crtil+Z一次性调整为rem单位 - 注意为body设置基础px值,防止页面渲染问题
body上的font-size主要是针对字体的,html上的font-size主要是针对布局的
最终代码:
html { font-size:26.666667vw;}
body {font-size:16px;}
/*布局代码区域*/
设计图以iphone6/7/8 375尺寸为准,直接量取px即可,
后续通过VScode工具(px to rem)设置好参数 Number of pixels per 1rem项目为100
然后圈选CSS样式alt+z即可完成转化工作