做挪动端页面有一段时间了,总结下工作中罕用的几种挪动端适配计划。
根底
网上曾经有十分多的基础知识总结,不再赘诉,详情能够见
《对于挪动端适配,你必须要晓得的》
《不要再问我挪动适配的问题了》
其中容易搞混的概念是视口
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,viewport-fit=cover">
meta
标签中的viewport
属性,就是视图
的含意
视口分为
- 布局视口
- 视觉视口
- 现实视口
布局视口
也就是<meta name="viewport" content="width=device-width">
中width
属性的含意
咱们在css中写的所有款式,就是绝对于布局视口
进行布局的
默认状况下,挪动端的布局视口并不是屏幕宽度,而是个别在768px ~ 1024px间(大部分状况下980px)
能够通过document.documentElement.clientWidth
获取 (依据width
和initial-scale
来确定)
视觉视口
视觉视口是指用户通过设施屏幕看到的区域,默认等于以后浏览器的窗口大小(当initial-scale
为1)
当用户对浏览器进行缩放时,不会扭转布局视口的大小,所以页面布局是不变的,然而缩放会扭转觉视口的大小
能够通过window.innerWidth
获取 (会随着缩放进行扭转)
放大页面,此时window.innerWidth
反而减小 (页面放大,你看到的货色也变少了)
现实视口
现实视口是指网站在挪动设施中的现实大小,这个大小就是设施的屏幕大小
也就是<meta name="viewport" content="width=device-width">
中device-width
的含意
能够通过screen.width
获取 (常量,不会扭转)
initial-scale
<meta name="viewport" content="width=device-width, initial-scale=0.5">
依据公式initial-scale = 现实视口宽度 / 视觉视口宽度
假如现实视口宽度为414px
(device-width),此时设置initial-scale
为0.5,那么视觉视口宽度就是414 / 0.5 = 818
如果这时你获取document.documentElement.clientWidth
(布局视口)的值,会发现不是414px
而是818px
论断: 布局视口宽度取的是width和视觉视口宽度的最大值
思考题:
<meta name="viewport" content="width=600, initial-scale=2">
假如现实视口宽度为414px
(device-width),此时document.documentElement.clientWidth
(布局视口)的值是多少?
视觉视口 = 414 / 2 = 207布局视口 = Math.max(207, 600)布局视口 = 600
总结
document.documentElement.clientWidth
: 布局视口,css中个别写成width=device-width
window.innerWidth
: 视觉视口,页面缩放都会实时扭转该值screen.width
: 现实视口,页面屏幕大小(设施独立像素),也就是css中的device-width
常见适配计划
简略一句话概括:挪动端适配就是在进行屏幕宽度
的等比例缩放:
平时咱们开发中,拿到的挪动端设计稿个别是750 * 1334
尺寸大小( iPhone6 的设施像素为规范的设计图)。那如果在750px
设计稿上量出的元素宽度为100px
,那么在375px
宽度的屏幕下,这个元素宽度就应该等比例缩放成50px
。
所以适配的难点是:如果实现页面的等比例缩放?
Rem 计划
该计划的外围就是:所有须要动静布局的元素,不再应用px
固定尺寸,而是采纳rem
绝对尺寸
rem
的大小是绝对于根元素html
的字体大小:如果html
的font-size
为100px,那么1rem
就等于100px
当初咱们假设:
750px
屏幕下 html
的font-size
为100px,也就是1rem
为100px,那么200px
宽度的.box
元素,就应该写成2rem
.box { /* 750px屏幕下,200px */ width: 2rem;}
那么当初:
375px
屏幕下,咱们须要.box
元素渲染成100px
.box { width: 2rem;}
因为.box
的宽度依然是2rem
,因而,这时候咱们就须要1rem
为50px,也就是说,此时html
的font-size
为50px
于是此时,咱们能够得出一个公式:
(750) / (100) = (以后屏幕尺寸) / (以后屏幕1rem)
把这个公式进行一次数学转换就能失去:
(以后屏幕1rem) = 100 * (以后屏幕尺寸) / 750
翻译成js语言就是
document.documentElement.style.fontSize = 100 * (document.documentElement.clientWidth) / 750 + 'px';
将代码优化一下
const PAGE_WIDTH = 750; // 设计稿的宽度 const PAGE_FONT_SIZE = 100;// 设计稿1rem的大小const setView = () => { //设置html标签的fontSize document.documentElement.style.fontSize = PAGE_FONT_SIZE * (document.documentElement.clientWidth) / PAGE_WIDTH + 'px';}window.onresize = setView; // 如果窗口大小产生扭转,就触发 setView 事件setView()
思考到Andorid端字体渲染的问题以及页面大小变动的监听,最终的代码如下:
(function () { var timer = null; var PAGE_WIDTH = 750; // 设计稿的宽度 var PAGE_FONT_SIZE = 100;// 设计稿1rem的大小 function onResize() { var e = PAGE_FONT_SIZE * document.documentElement.clientWidth / PAGE_WIDTH; document.documentElement.style.fontSize = e + 'px'; // 二次计算缩放像素,解决挪动端webkit字体缩放bug var realitySize = parseFloat(window.getComputedStyle(document.documentElement).fontSize); if (e !== realitySize) { e = e * e / realitySize; document.documentElement.style.fontSize = e + 'px'; } } window.addEventListener('resize', function () { if (timer) clearTimeout(timer); timer = setTimeout(onResize, 100); }); onResize();})();
留神的是:咱们取 100px
作为设计稿的1rem,是因为不便计算,比方设计稿上量出250px
,咱们就能够很容易的计算出为2.5rem
。
咱们当然也能够把 50px
作为设计稿的1rem,这时设计稿上的250px
,就要写成5rem
。
其实咱们也能够借助于postcss-pxtorem或者SCSS
函数来帮咱们主动转换单位
@function px2rem($px) { // 根元素字体为100px @return $px / 100 * 1rem;}.box { width: px2rem(200);}
通过Rem计划,须要动静缩放的元素,咱们应用rem
绝对单位,不须要缩放的元素,咱们依然能够应用px
固定单位。
不过在大屏设施下(例如ipad或者pc端),因为咱们的页面是等比例缩放,这时候页面的元素会被放大很多(屏幕宽度大,导致根元素字体1rem也变大)。然而在大屏下,咱们真正心愿的是用户看到更多的内容,这时候咱们能够应用媒体查问的形式来限度根元素的字体,从而避免在大屏下元素过大的问题。
@media screen and (min-width: 450px) { html { font-size: 50px !important; }}
或者批改js脚本的逻辑
const PAGE_WIDTH = 750; // 设计稿的宽度 let PAGE_FONT_SIZE = 100;// 设计稿1rem的大小const setView = () => { if (document.documentElement.clientWidth > 450) { // 大屏下减小根元素字体 PAGE_FONT_SIZE = 50; } document.documentElement.style.fontSize = PAGE_FONT_SIZE * (document.documentElement.clientWidth) / PAGE_WIDTH + 'px';}
VW 计划
vw 是绝对单位,1vw 示意屏幕宽度的 1%
其实咱们的REM计划
就是VW计划
的模仿,之前咱们有一个公式:
(750) / (100) = (以后屏幕尺寸) / (以后屏幕1rem)
换一个转换形式:
(以后屏幕1rem) = (以后屏幕尺寸) / 7.5
而 vw 单位其实就是:
(以后屏幕1vw) = (以后屏幕尺寸) / 100
因而,REM计划
就是用 JS 把屏幕宽度分成了7.5份,而 CSS3 中新增的vw
单位,原生实现了把屏幕宽度分成了100份
所以,在VW计划
中,咱们不再须要应用JS脚本了!
750px
设计稿中,1vw
等于7.5px
(750 / 100),因而,在设计稿中,量出200px
的宽度,就因为写成26.667vw
(200 / 7.5)
.box { /* 750px屏幕下,200px */ width: 26.667vw;}
不过应用vw
换算,并不像rem
那么不便,这时候咱们能够借助postcss-px-to-viewport或者SCSS
函数来帮咱们主动转换单位
@function px2vw($px) { @return $px / 750 * 100vw;}.box { width: px2vw(200);}
同样,在大屏设施下,因为屏幕宽度大,所以页面的元素同样会放大很多(屏幕宽度大,1vw也很大)。然而因为vw
是绝对屏幕宽度的,所以咱们不能像REM计划
中一样,手动管制html
的根字体大小,这也是应用VW计划
的一个毛病。
REM + VW 计划
REM计划
的劣势是能够手动管制rem
的大小,避免屏幕太大时,页面元素也缩放很大,然而毛病就是须要应用JS
。VW计划
刚好相同,无需应用JS
然而无奈手动管制vw
的大小。
其实咱们能够把两者联合:
html { /* 750px 的设计图,1rem = 100px */ font-size: calc(100 * 100vw / 750);}.box { /* 750px屏幕下,200px */ width: 2rem;}
对于布局元素,咱们依然应用rem
单位。然而对于根元素的字体大小,咱们不须要应用JS来动静计算了
100 * (document.documentElement.clientWidth) / 750
这段js能够间接应用css来实现
calc(100 * 100vw / 750)
对于大屏设施,咱们应用媒体查问
@media screen and (min-width: 450px) { html { font-size: calc(50 * 100vw / 750); }}
更具体的vw+rem布局计划
能够见《基于vw等viewport视区单位配合rem响应式排版和布局》
viewport 缩放计划
还有一种更简略粗犷的办法,就是咱们设置initial-scale
咱们的布局齐全基于设计稿750px
,布局元素单位也应用px
固定单位 (布局视口写死750px)
对于375px
宽度,咱们就将整个页面缩放0.5
:
<meta name="viewport" content="width=750, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5, user-scalable=0">
<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"> <title>demo</title> <script> var clientWidth = document.documentElement.clientWidth; var viewport = document.querySelector('meta[name="viewport"]'); var viewportWidth = 750; var viewportScale = clientWidth / viewportWidth; viewport.setAttribute('content', 'width=' + viewportWidth + ', initial-scale=' + viewportScale + ', minimum-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ', user-scalable=0'); </script></head>
.box { width: 200px;}
此计划的毛病: 整个页面都被缩放了,对于不想缩放的元素无法控制。
市面上一些营销H5页面,因为是通过后盾可视化拖拽搭建进去的,为了适配各种尺寸的屏幕,该计划是老本最低的实现(易企秀就是应用这种计划)
实战
咱们拿线上B站的会员购作为示例
- rem计划
- vw计划
- rem+vw计划
- viewport计划
请应用chrome开发者工具模仿挪动端设施查看
源码间接右键查看即可,代码没有通过压缩,能够很直观的看到各种计划的css适配写法
参考
- 挪动端适配有哪几种计划?
- 不要再问我挪动适配的问题了
- 对于挪动端适配,你必须要晓得的
- 基于vw等viewport视区单位配合rem响应式排版和布局