- 【序】今天刷到一篇公众号的文章主题是移动端适配的相关基础概念,那么就通过阅读基础概念,从业务的角度来做个总结,文章地址
问题一
- 【疑惑】 当我们拿到移动端的设计稿,应该从何处下手?
- 【解惑】 设计稿往往是使用px单位进行标注的,要完全呈现设计稿在不同手机上的适配,首先需要了解一下动态单位,动态单位有,vh,vw,vm,rem,%,接下来细数一下各个单位的基本概念。
- px
用的最多的px,其意义就是,一个像素点
- 【缺点】设计稿往往只针对某一个分辨率,一旦分辨率缩小或者变大,就会导致样式变形
- 【优点】无须计算,便于开发
-
viewport unit
vh与vw都是css3才出的单位,vh代表视口高度总像素比,vw代表视口宽度总像素比,例如一个1300*800像素的屏幕,1vh就是1/800,1vw就是1/1300
此外还有两者取一的vmin和vmax,
vmin表示高度和宽度谁小取谁的,配合padding使用padding: 10vmin 1rem;
能够获得较合适的顶部和底部展示
vmax表示高度和宽度谁大取谁,可以使元素保持宽高比(用于图片固定宽高比展示比较有用)
rem,em
rem,em是通过对字体大小来计算宽度的单位,em假设父级的font-size是16px,那么1em=16px,而rem和em相当,但是对标html标签上设置的font-size%
%分号就是父级宽度/高度的百分比,如果父级没有给定宽度/高度,那么就会失效
【缺点】 不够精确
【优点】 简单易用,能够保持元素的原始比例,通常在pc端可以保证布局在一定范围内适应分辨率
问题二
- 【疑惑】 接下来我们要学习像素的概念,像素分为物理像素,设备独立像素,css像素
- 【解惑】
物理像素
即设备横向有多少个像素,纵向有多少个像素,是非常直观,单位的px设备独立像素( DeviceIndependentPixels 简称 DIP或DP)
同样的1单位物理像素,假设手机屏幕物理宽度相同,但是其中一个手机相同的宽度上比其他手机多一倍的像素,那么这1 单位物理像素,在物理像素多的手机上的显示就会变得更小,但是由于手机物理宽度不同&物理像素的不同,那就需要一个单位来告诉所有设备某个图形的宽度到底是在这个手机大小是多少?这个单位就DP,此时1DP在所有设备上的大小都相等了。
【延申】在Chrome的模拟器中显示的设备大小单位其实就是DP
css像素
css像素,css像素 = 页面的缩放系数*设备独立像素设计像素
设计像素是实际展示的内容的像素,通常是UI提供的设计稿的像素参照,详细概念看问题三
问题三
- 【疑惑】 既然拥有了设备独立像素的概念,那么只需要将物理像素转化为设备独立像素,就可以完美适配全部机型了吗?
- 【解惑】 并不够,设备独立像素是通过物理宽度与物理像素计算出来的,但是有的设备,物理像素上就是要展示更高分辨率的展示的效果,例如iPhone6、7、8Plus的实际物理像素是 1080 * 1920,设备独立像素是414DP * 736DP,但是实际上展示1242PX * 2208PX分辨率的内容(称为设计像素),此时仅靠设备独立像素就不够了,还需要设备像素比 (device pixel ratio简称 dpr)
此时,1dp=1px/dpr,1px = 1dp*dpr - 【延申】设备像素比在浏览器中可以通过
window.devicePixelRatio
来获取,但是devicePixelRatio的兼容性IE,firefox兼容问题不推荐使用
问题四
- 【疑惑】 手机上网刚出现的时候,是如何针对电脑屏幕开发的网页的?
- 【解惑】 此时就要学习 视口 的概念,视口分为布局视口,视觉视口,理想视口
- 布局视口(layout viewport)
就是我们的css内容的大小 -
视觉视口(visual viewport)
就是手机屏幕所展现出来的大小
- 理想视口( ideal viewport)
也就是说最适合的宽度,即布局视口等于视觉视口的宽度,那些针对idel viewport而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美呈现给用户,布局视口要适应视觉视口,那么就必须先将视觉视口固定下来,一般使用以下代码,就能够将默认的layout viewport等同于visual viewport 此时我们就只需要考虑visual viewport即可
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
此时设备物理宽度和我们的页面宽度为一比一了,接下来就只用考虑物理像素密度dpr了
viewport unit自适应方案
该方案由于采用了视口单位,则viewport的meta设置也不需要了
方案中,我们需要将设计稿中的px按照比例转换为vw单位,这样就能保证在不同的宽度中获得统一的比例
//iPhone 6尺寸作为设计稿基准
$vm_base: 375;
@function vw($px) {
@return ($px / $vm_base) * 100vw;
}
接下来就可以愉快的使用该方法按照设计稿去计算宽高,间距,字体大小了
.mod_nav {
background-color: #fff;
&_list {
display: flex;
padding: vm(15) vm(10) vm(10); // 内间距
&_item {
flex: 1;
text-align: center;
font-size: vm(10); // 字体大小
&_logo {
display: block;
margin: 0 auto;
width: vm(40); // 宽度
height: vm(40); // 高度
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
}
&_name {
margin-top: vm(2);
}
}
}
}
高清屏下1px单边框解决方案原理:
.scale-1px-bottom {
position: relative;
&::after {
// 实现1物理像素的下边框线
content: '';
position: absolute;
z-index: 1;
pointer-events: none;
background-color: #ddd;
height: 1px;
left: 0;
right: 0;
top: 0;
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
-webkit-transform: scaleY(0.5);
-webkit-transform-origin: 50% 0%;
}
}
}
实际项目sass实现参考
保持图片宽高比实现方案
.mod_banner {
position: relative;
padding-top: percentage(100/700); // 使用padding-top,100是稿子上的高度,700是设计稿的比例
height: 0;
overflow: hidden;
img {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
}
}
结合rem优化方案
- 可以方便的通过改变计算方式过度到viewport unit
- 增加了宽度最大值最小值,在ipad等大屏幕上用户体验更好
【延伸】手机的实际分辨率是设计稿的两倍?
答案:因为设计师拿去设计的稿子是按照手机的实际宽度375去设计的,但是程序员去实现时,考虑到相同宽度拥有更多像素点即dpr,因此实际分辨率是1dpdpr,即iPhone6的dpr=2,那么实际分辨率为3752。
// rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推
// 根元素大小使用 vw 单位
$vm_design: 375; //设计稿参照iPhone6的大小
$vm_fontsize: $vm_base * 2 / 10; // 因为一般实际分辨率是设计稿的两倍,所以需要先乘2,再除10获得设计稿上的实际1rem的值
@function rem($px) {
@return ($px / $vm_fontsize ) * 1rem;
}
html {
font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw; //因为默认需要占用20vw
// 同时,通过Media Queries 限制根元素最大最小值
@media screen and (max-width: 320px) {
font-size: 64px; //当屏幕宽度小于320px 则1rem = 64px; 该值来源于320*2
}
@media screen and (min-width: 540px) {
font-size: 108px; // 当屏幕宽度大于540px 则1rem = 108px; 该值来源于540*2
}
}
// body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小
body {
max-width: 540px;
min-width: 320px;
}
总结
- 当我们拿到设计稿,我们要清楚设计稿的分辨率,设计稿是为移动端还是pc端设计的,pc端的dpr为1,移动端一般以dpr=2为主
- 第二计算rem,1rem为实际分辨率的1/10