rem屏幕适配
通过使用rem单位使网页,在不同屏幕尺寸下正常显示的一种移动端开发方案;
rem是CSS3新增的一个相对长度单位,相对于根元素(html)的font-size进行计算;
简单屏幕适配方案
原理
设置<meta>
标签、获取视口宽度,动态设置根元素(HTML)的fontsize。
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Document</title>
<style>
html{
font-size: 100px;
}
body{
margin: 0;
padding: 0;
}
div{
height: 1rem;
background-color: red;
border-bottom: 1px solid #000;
}
</style>
<script>
setRemUnit();
addEventListener('resize', setRemUnit);
function setRemUnit(){
// 获取视口宽度
let viewWidth = document.documentElement.getBoundingClientRect().width
|| window.innerWidth;
// 基于设计稿 375 宽进行设置,可根据自己需要修改
let rabtio = viewWidth / 375;
// 设置fontSize,html的fontsize为100; 1rem = 100px
let fontSize = rabtio * 100;
// 修改HTML的fontsize
document.documentElement.style.fontSize = fontSize + 'px';
}
</script>
</head>
<body>
<div></div>
</body>
</html>
resize 事件是在浏览器窗口被重置时触发的,如当用户调整窗口大小,或者最大化、最小化、恢复窗口大小显示时触发 resize 事件。
Document.documentElement 是一个会返回文档对象(document)的根元素的只读属性(如HTML文档的
<html>
元素)。
页面效果
缺点
简单屏幕适配方案的1像素边框问题;
1像素边框问题
同样是1像素的边框,在不同清晰度的屏幕下、不同DPR下、相同的CSS像素渲染出的物理像素去却相同。
DPR为1时,1px渲染出1物理像素;
DPR为2时,1px渲染出2物理像素;
DPR为3时,1px渲染出3物理像素;
通用屏幕适配方案
通用屏幕适配方案解决了简单屏幕适配方案的1像素边框问题。
原理
在不同dpr(设备像素比)下,动态设置<meta>
标签的scale(页面缩放),解决了1像素边框问题。
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Document</title>
<style>
html{
font-size: 100px;
}
body{
margin: 0;
padding: 0;
}
div{
height: 1rem;
background-color: red;
border-bottom: 1px solid #000;
}
</style>
<script>
// dpr => scale = 1/dpr
let viewportEl = document.querySelector('meta[name = viewport]');
let dpr = window.devicePixelRatio || 1;
dpr = dpr >= 3 ? 3: (dpr >= 2 ? 2: 1);
document.documentElement.setAttribute('data-dpr', dpr);
let scale = 1 / dpr;
let content = 'width=device-width, initial-scale=' + scale + 'px';
if(viewportEl){
viewportEl.setAttribute('content', content);
}else{
viewportEl = document.createElement('meta');
viewportEl.setAttribute('name', 'viewport');
viewportEl.setAttribute('content', content);
document.head.appendChild(viewportEl);
}
setRemUnit();
window.addEventListener('resize', setRemUnit);
function setRemUnit(){
// 获取视口宽度
let viewWidth = document.documentElement.getBoundingClientRect().width
|| window.innerWidth;
// 基于设计稿 375 宽进行设置,可根据自己需要修改
let rabtio = viewWidth / 375;
// 设置fontSize,html的fontsize为100; 1rem = 100px
let fontSize = rabtio * 100;
// 修改HTML的fontsize
document.documentElement.style.fontSize = fontSize + 'px';
}
</script>
</head>
<body>
<div></div>
</body>
</html>
HTML DOM setAttribute() 方法
例:element.setAttribute(attributename,attributevalue);
setAttribute() 方法添加指定的属性,并为其赋指定的值。
如果这个指定的属性已存在,则仅进行修改。
优化
在原有功能的基础上加了minwidth、maxwidth视口限制;
当视口大于maxwidth(小于minwidth)时,页面将按maxwidth(minwidth)时渲染;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Document</title>
<style>
html{
font-size: 100px;
}
body{
margin: 0;
padding: 0;
}
div{
height: 1rem;
background-color: red;
border-bottom: 1px solid #000;
}
</style>
<script>
// dpr => scale = 1/dpr
let viewportEl = document.querySelector('meta[name = viewport]');
let dpr = window.devicePixelRatio || 1;
let minwidth =320;
let maxwidth =540;
dpr = dpr >= 3 ? 3: (dpr >= 2 ? 2: 1);
document.documentElement.setAttribute('data-dpr', dpr);
document.documentElement.setAttribute('minwidth', minwidth);
document.documentElement.setAttribute('maxwidth', maxwidth);
let scale = 1 / dpr;
let content = 'width=device-width, initial-scale=' + scale + 'px';
if(viewportEl){
viewportEl.setAttribute('content', content);
}else{
viewportEl = document.createElement('meta');
viewportEl.setAttribute('name', 'viewport');
viewportEl.setAttribute('content', content);
document.head.appendChild(viewportEl);
}
setRemUnit();
window.addEventListener('resize', setRemUnit);
function setRemUnit(){
// 获取视口宽度
let viewWidth = document.documentElement.getBoundingClientRect().width
|| window.innerWidth;
// minwidth、maxwidth优化
if(maxwidth && (viewWidth / dpr > maxwidth)){
viewWidth = maxwidth * dpr;
}else if(minwidth && (viewWidth / dpr < minwidth)){
viewWidth = minwidth * dpr;
}
// 基于设计稿 375 宽进行设置,可根据自己需要修改
let rabtio = viewWidth / 375;
// 设置fontSize,html的fontsize为100; 1rem = 100px
let fontSize = rabtio * 100;
// 修改HTML的fontsize
document.documentElement.style.fontSize = fontSize + 'px';
}
</script>
</head>
<body>
<div></div>
</body>
</html>