html5移动端自适应(h5手机自适应)
众所周知,前端的移动端适配问题是个老生常谈的问题,面试中也是经常被问到,面试官经常是一句“你是怎么做移动端适配的”或者“谈谈你对移动端适配的理解”就让面试者感觉不知道该从什么地方下手去回答这个问题。手机市场日渐丰富的同时,给我们前端开发人员带来的网页内容自适应屏幕尺寸进行显示的问题也日渐凸显出来。
本文将针对移动端适配问题进行总结,总结一下各主流适配方案以及在主流框架中是怎么做适配的,希望通过本文能让读者在遇到移动端适配的面试问题时不再不知所措。
相关概念
要搞明白移动端适配问题,就要先搞明白屏幕、像素和视口三个概念。
一、屏幕
1 屏幕大小
屏幕大小指屏幕的对角线的长度,单位一般是英寸。常见的手机屏幕大小 3.5、4、4.7、5.0、5.5、6.0等。
常见手机屏幕查看网址: http://screensiz.es/ 。
注意:
英寸的英文为 inch , 英尺的英文是 foot
1foot = 12inch
1inch = 2.54cm
02 屏幕分辨率
屏幕分辨率是指屏幕横纵向上的像素点数。一般表示形式 x * y 或者 y * x 表示。例如 IPhone 6 的屏幕分辨率为 750 * 1334,华为 P30 的分辨率为 2340 * 1080。
展开全文
注意:
屏幕分辨率是一个固定值,生产出来就固定了,无论手机屏幕还是电脑屏幕。
屏幕分辨率与显示分辨率不同。计算机可以修改显示分辨率,信号传递给屏幕,在屏幕上显示。
1080P 的分辨率是1920x1080 720P 1280 * 720。
2K 屏幕是单一方向分辨率具有约 2000 像素的显示设备。最标准的 2K 分辨率为 2048×1024。
几款手机的屏幕分辨率:
二、像素
01 物理像素
设备像素 / 物理像素是一个长度单位。1 物理像素对应显示设备中一个微小的物理部件。
设备像素是手机屏幕的一个参数,由手机制造商决定。例如 IPhone 6 的物理像素为 750 * 1334。
02 设备独立像素
设备独立像素,简称 DIP(device-independent pixel),又称为设备无关像素,是一个长度计量单位。
设备独立像素也是手机屏幕的一个参数,由手机制造商决定。例如IPhone 6 的设备独立像素为 375 * 667。
1 个设备独立像素可以认为是计算机坐标系统中的一个点,代表可以通过程序控制使用的虚拟像素。
普通屏幕下 1 设备独立像素 等于 1 物理像素。
高清屏幕下 1 设备独立像素 等于 N 物理像素。
设备独立像素的出现,使得即使在高分辨率的屏幕下,也可以正常尺寸的显示元素,代码不受到设备的影响。
比如 Retina 屏幕:
Retina 是苹果公司 2010 年推出的一种显示标准,是把更多的像素点压缩至一块屏幕里,从而达到更高的分辨率并提高屏幕显示的细腻程度。
几款手机的屏幕像素参数,更多请查看 https://uiiiuiii.com/screen/。
03 CSS 像素
CSS 像素又称为虚拟像素,是一个相对单位,单位为 px。
CSS 像素不能直接跟现实中的长度单位换算。
CSS 像素主要用在 CSS 与 JS 中控制元素的大小与位置。
04 位图像素
位图图像亦称为点阵图像或栅格图像,是由单个的像素点组成的。放大后会失真。(png jpeg jpg gif)
矢量图,也称为面向对象的图像或绘图图像,在数学上定义为一系列由线连接的点。放大后不会失真。软件有Adobe Illustrator,Sketch (svg)。
位图像素也是一个长度单位。位图像素是栅格图像(如:png,jpg,gif等)最小的数据单元。
1个位图像素对应于1个物理像素,图片才能得到完美清晰的展示(马赛克)。
05 像素之间的关系
页面不缩放的情况下,CSS 像素 == 独立设备像素 == 逻辑像素 == DIP == 位图像素。
在一个标准的显示密度下(普通屏),一个 CSS 像素对应着一个设备像素,高清屏幕下一个 CSS 像素 等于 N 个物理像素。
06 像素密度
屏幕上每英寸可以显示的像素点的数量,单位是 ppi (pixels per inch ),这里还有另一个单位 dpi(dots per inch),两个值的计算方式都一样,只是使用的场景不同。PPI 主要用来衡量屏幕,DPI 用来衡量打印机,鼠标等设备。
苹果曾经给出一个标准:手机屏幕达到 300PPI、平板屏幕达到 220PPI、笔记本电脑屏幕达到 200PPI 即可认为是 Retina 屏幕。
07 像素比
像素比(DPR dpr):单一方向上设备物理像素和设备独立像素的比例。
window.devicePixelRatio
像素比的作用:
程序可以根据像素比来显示不同的图片,达到清晰显示网页的效果。
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.logo { background-image: url('./image/logo@2x.png'); }
}
并不是所有的图片都这样处理,只需要处理那些页面布局需要的图片和图标即可。
三、视口
01 PC端
在 PC 端,视口指的是浏览器的可视区域。其宽度和浏览器窗口的宽度保持一致。在 CSS 标准文档中,视口也被称为初始包含块,它是所有 CSS 百分比宽度推算的根源。
02 移动端
移动端的视口与 PC 端不同,有三个视口:
布局视口
视觉视口
理想视口
一般移动设备的浏览器都默认定义一个虚拟的布局视口(layout viewport),用于解决早期的页面在手机上显示的问题。视口大小由浏览器厂商决定,大多数移动设备的布局视口大小为 980px。
获取方式:
document.documentElement.clientWidth
document.documentElement.clientHeight
b. 视觉视口:视觉视口就是用户可见的区域。
获取方式:
window.innerWidth
window.innerHeight
注:不缩放的情况下,视觉视口宽度 == 布局视口宽度。
c.理想视口:宽度与屏幕同宽(设备独立像素)的布局视口称为理想视口。
理想视口的好处:
用户不需要缩放和滚动条就能看到网站的全部内容。
针对移动端的设计稿更容易开发。
注意:理想视口不是真实存在的视口
设置理想视口的方法:
meta name="viewport" content="width=device-width" /// 或者
meta name="viewport" content="initial-scale=1.0" /// 合体
meta name="viewport" content="width=device-width,initial-scale=1.0" /
移动端适配
了解了上面这些相关概念后,咱们来进入主题,看看移动端适配。
移动端设备的屏幕尺寸繁多,要想让页面的呈现统一,需要对不同尺寸的设备进行适配。适配的方式通常有4种:
媒体查询(meida queries)
viewport + rem适配
Flex布局
vm/vh
01 媒体查询
meida queries 的方式可以说是我早期采用的布局方式,它主要是通过查询设备的宽度来执行不同的 css 代码,最终达到界面的配置。核心语法是:
@media screen add ( max-width:768px ){
/*当屏幕尺寸小于768px时,应用下面的css样式*/
}
02 viewport + rem 适配
em 和 rem 都是 CSS 中的长度单位。而且两个都是相对长度单位,不过两个有点区别:
em 相对的是父级元素的字体大小,
rem 相对的是根元素的字体大小 。
核心是等比缩放
rem 适配的策略有以下几种:
方法一
先按照 IPhone 6 进行页面布局,再进行适配
1、完美视口设置
2、设计稿总宽 375 布局
3、设置 font-size 100px 尺寸转为 rem
4、增加 JS 代码进行页面适配
方法二
编写时直接使用 rem 单位进行布局
1、完美视口设置
2、总宽 375 布局
3、以 font-size 100px 进行尺寸换算,设置 rem
4、增加 JS 代码进行页面适配
方法三
选择一个设计稿宽度的比例尺寸作为根元素的字体大小
1、完美视口设置
2、通过 JS 设置页面的根元素字体大小。可以除以 10 也可以除以其他的数字
3、根据设计稿使用 rem 设置元素大小
03 flex布局
以天猫的实现方式进行说明:
它的viewport是固定的:
meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"
高度定死,宽度自适应,元素都采用px做单位。
随着屏幕宽度变化,页面也会跟着变化,效果就和PC页面的流体布局差不多,在哪个宽度需要调整的时候使用响应式布局调调就行,这样就实现了适配。
04 vw/vh
vw 是相对单位,1vw 表示屏幕宽度的 1%。基于此,我们可以把所有需要适配屏幕大小等比缩放的元素都使用 vw 作为单位。不需要缩放的元素使用 px 做单位。
vw/vh适配一般应用在框架中,以vue框架为例,只需要进行以下下几步即可实现适配:
1、安装 postcss-px-to-viewport
npm i postcss-px-to-viewport
2、在项目根目录下建名为vue.config.js的文件(不懂为什么要建名为vue.config.js的可以看一下vue-cli下webpack相关)
3、在vue.config.js中引入postcss-px-to-viewport
const pxtovw = require('postcss-px-to-viewport')
4、vue.config.js中配置项如下
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', // 需要转换的单位,默认为"px"
viewportWidth: 1920, // 设计稿的视口宽度
unitPrecision: 5, // 单位转换后保留的精度
propList: ['*'], // 能转化为vw的属性列表
viewportUnit: 'vw', // 希望使用的视口单位
fontViewportUnit: 'vw', // 字体使用的视口单位
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: undefined, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: 'vw', // 横屏时使用的单位
landscapeWidth: 1920 // 横屏时使用的视口宽度
}
}
}
5、重启项目就能自适应了
05 1px边框问题
高清屏幕下 1px 对应更多的物理像素,所以 1 像素边框看起来比较粗,解决方法如下:
方法一
1、边框使用伪类选择器,或者单独的元素实现。例如底部边框
.box2::after{
content:'';
height:1px;
width:100%;
position:absolute;
left:0;
bottom:0;
background:#000;
}
2、在高清屏幕下设置
@media screen and (-webkit-min-device-pixel-ratio: 2){
.box2{transform:scaleY(0.5);}
}
@media screen and (-webkit-min-device-pixel-ratio: 3){
.box2{transform:scaleY(0.33333);}
}
方法二
1、rem 页面布局
var fontSize = 50;
document.documentElement.style.fontSize = '50'+ px;
2、元素的边框设置为 1px
3、通过 viewport 中的 initial-scale 将页面整体缩小
var dpr = window.devicePixelRatio;
viewport.setAttribute('content', 'user-scalable=no, initial-scale='+1/dpr + ',user-scalable=no');
4、重新设置根元素字体
document.documentElement.style.fontSize = fontSize * dpr + 'px';
总结
本文中例举的适配方案是目前比较主流的适配方案,大家可以根据项目需求来使用不同的适配方案,也希望本文能够帮助到面试的同学在适配这方面的问题上不再不知所措,跟面试官交流的时候可以问有所答,畅所欲言。