悟了两星期终于悟了,移动端适配核心思想——没讲懂揍我
移动端开发与pc端适配的不同
pc端布局常用方案
所谓适配,就是指我们的项目开发出来用户在不同虚拟环境、不同硬件环境等等各种情况下有一个稳定、正常的展示(简单理解就是不会排版混乱)
先来回顾一下pc端的项目我们如何写页面做到适配的,大部分页面都是采用版心布局的形式。也就是说所有的内容都写在版心容器盒子里,这个容器盒子设置:margin: 0 auto; & min-width: <版心宽度> & width: <版心宽度>
就可以保证:
当用户的屏幕(浏览器)宽度很大,或者缩放浏览器到很小比例时,此时浏览器的宽度大于版心盒子的
width
,版心容器会自动生成margin-left & margin-right
,总会保证版心容器处于页面的正中心。这里可以提一嘴pc端浏览器缩放的原理:页面所有元素的css宽高都不会改变,只是css像素的在屏幕上展示的大小缩水了,具体点来说,原本700px * 700px的盒子在浏览器上用10cm * 10cm面积(的物理像素)渲染,但现在用原本
<浏览器缩放比率> * 10cm * 10cm
面积(的物理像素)渲染。当用户的屏幕小于版心盒子的
width
,出现横向滚动条,版心盒子的左右margin
为0,width
内的内容可滑动滚动条完整查看。
可以参考大淘宝pc端官网就是版心布局的实践。
好了,那么问题来了,移动端为啥不能照搬pc端的这种适配方案呢?
我们有必要先梳理一下移动端对页面进行渲染展示的逻辑:
移动端页面渲染的逻辑
无<meta name="viewport">
的情况
在html文档里没有<meta name="viewport">
标签配置的情况下(通过对比即可理解<meta>
标签的意义):
plus:如下整个流程篇口语话主要是梳理核心思路,没有一字一板的细节考究
- 我们项目中布局写的所有dom元素的css大小都正常(完全按照css大小的预期)在一个非常大的空间进行渲染,这个空间可能不是无限大,但是为了帮助理解,因为这个空间的大小一般不影响我们项目的正常布局,所以我们可以理解为无限大,这是第一步,即项目页面就像在pc端一样完全按照css写的大小以及布局进行渲染。
- 因为我们的移动端设备没有电脑屏幕那么大,所以会把第一步在“很大空间”渲染的页面进行缩小,直至缩小到我们的大页面宽度正好与手机屏幕的宽度一样即可。所以第二步相当于为了让用户把页面看全,手机自动把页面缩小至屏幕内。
为了帮助大家理解,也验证我上面的说法,我写了如下的pc端的版心布局的页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style>
.container {
width: 1200px;
min-width: 1200px;
margin: 0 auto;
border: 2px solid red;
background: yellow;
}
.container .content {
height: 3000px;
}
</style>
<body>
<div class="container">
<div class="content">内容</div>
</div>
</body>
</html>
我把上面的页面部署到osrc(一个国内的免费部署网站,类似于vercel)上了(不可用chrome浏览器的移动端去模拟移动端访问的场景,chrome浏览器只是模拟了屏幕大小,而并没有模拟移动端环境,也就是说根本不会处理<meta>
标签,所以这里我们需要部署),大家可以自行用pc端和移动端访问体验(实践一下绝对秒懂我上面的文字),为了照顾没有双端设备的读者,我截一下图(直接喂饭到胃哈哈)
pc端访问:
移动端访问:
清晰了吧兄弟们,我们写死的1200px宽的container
盒子因为手机本身没这么大,所以缩小之后塞进了手机屏幕中,仔细看手机中的文字,已经被缩小的看不清了。
配置<meta name="viewport">
的情况
暂时只给我们的index.html
中<meta name="viewport">
添加一个content="width=device-width, initial-scale=1.0"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container {
width: 1200px;
min-width: 1200px;
margin: 0 auto;
border: 2px solid red;
background: yellow;
}
.container .content {
height: 3000px;
}
</style>
<body>
<div class="container">
<div class="content">内容</div>
</div>
</body>
</html>
重新部署后访问查看效果,有meta的页面,部署地址,<meta>
标签是针对移动端的,所以pc端完全没影响,跟上面一样。现在我们访问移动端效果如下,我没有缩小图片,注意观察页面底部出现滚动条了(纵向滚动条有滚动所以文字没展示,不重要):
解释一下content="width=device-width, initial-scale=1.0"
的作用。
解读<meta>
& dip & 布局视口(自认为最精华,全网少数不带偏新人的解释)
其实相当于我们在content
字段中进行了两项配置,第一项是width=device-width
,第一个width
是指布局视口的宽度,引出概念,何为布局视口?还记得我们上面说的在没有<meta>
时的那个非常大的布局空间嘛,就是它!我们让这个空间的宽度等于device-width
,device-width
就是指dip
即设备独立像素,第二个概念,何为dip(device independent piexl设备独立像素)
呢?听我的,完全不要被网上各种乱七八糟的解释弄迷糊了,什么dpr,什么物理像素,我只能说那些东西与我们开发者并没有直接关系,笔者读了几户所有能搜到的各种移动端入门文章,一言难尽... ,我来给出对于dip
的理解,每一个型号的移动设备都具有的一个大小,这个大小是用设备独立像素dip来描述的,所以它仅仅是一个描述大小的单位,但是这个单位究竟是多大呢,换句话说dip有何特殊性呢?
在移动端不缩放的情况下,一个css像素等于一个设备独立像素dip
(chrome浏览器的移动端开发工具里显示的就是dip大小)也就是说,我们让布局视口的宽度等于设备的dip宽度,这里注意:布局视口由原来的”无限大“现在改为一个具体的数值,并不会影响页面的正常布局,页面还是会完整渲染, 只是最后不用缩小放进屏幕了,因为我们缩小的目的就是让布局视口完整的展现在屏幕中。因为屏幕不能展示完整整个页面的布局,所以底部出现滚动条。用户可以滚动访问页面全部内容。
其实这里initial-scale=1.0
的作用就是让移动端浏览器不自行缩放,不然的话浏览器会把如上页面再缩小,然后放到手机屏幕里去。
关于<meta name="viewport">
的最佳实践
简简单单如下:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
为什么说这是最佳实践,论证它其实还缺少一个关键点,也就是移动端css单位的选取,概括来说,width=device-width
配置与移动端css单位的选取两者相辅相成,共同构成了“最佳实践”。
先说一下css单位选取——以vw
为例:vw
是相对屏幕大小的一个长度单位,1vw
等于移动设备屏幕宽度的1%
。
如何理解“最佳实践”?
首先width=device-width
保证了无论何种机型的移动设备,我们开发时写页面的布局视口始终等于屏幕宽度,但看这一点,确实没啥用。如果再来一个条件:页面中所有长度单位用vw
来表达。细品!
如何细品?别忘了初心,我们的目标是在不同的移动设备上都能有统一的展示效果,开品:我们用不同dip
宽度的设备打开网页,首先布局视口的大小会随着设备dip
的不同而不同,也就是始终等于dip
宽度:
布局视口宽度 === 设备dip宽度,
并且我们的所有元素大小单位都是vw
,也就是说页面中所有元素大小都以屏幕宽度为参照物。最终的效果就是,一个dip宽度超级小的设备打开网页,与一个dip宽度非常大的设备打开网页,看到的页面内容是完全相似的,也就是每个元素在页面中所占的比例不同设备都一样(不同点就在于屏幕本身的大小不一样)!
一般<meta>
标签的content
中还会设置initial-scale=1.0, maximum-scale=1.0, user-scalable=no
,即不让页面进行缩放,感觉这个看需求吧,不让缩小应该是必须的,因为可以想一想,用户缩小完全没有意义呐!(需要大家自己去理解,属于只可意会),至于让不让放大,应该是看情况吧,反正移动端淘宝官网是允许放大的。
移动端适配方案理解
主流的有vw
方案、flexible + rem
方案,总而言之,把元素的大小用rem
来表示或者vw
表示,本质都是以手机屏幕宽度为参考,vw
比较直接,表达的意思就是1vw
等于手机屏幕宽度的百分之一;rem
比较间接,通过flexible.js
先把得知屏幕宽度是多少px
,然后设置<html>
的font-size
,进而所有元素的rem
其实还是表达占屏幕宽度的百分之多少。
当然两种方案都有一些技术细节问题需要解决,比如1px
问题、安全区域问题等等。这里就不多说了。
相信能一步一步走到这里的同志,对移动端适配绝对有了一个清晰的把握。
2023.6.19,3: 59。
来源:juejin.cn/post/7246001188448731196