整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端必备:自适应所有分辨率的神技

前端必备:自适应所有分辨率的神技

为我在公司的开发电脑的分辨率是1920,所以一开始我实在1920分辨率下写得css样式表,然后完成之后放到投影的机器上做演示,分辨率是1400,结果就直接悲剧了。

在项目中遇到各种分辨率的调整问题,看到各位小伙伴们煎熬的表情,真的是于心不忍,于是查询对应的解决办法,从cssAPI中找到前人提供的高级用法:

<!DOCTYPE html> 
<html> 
	<head> 
		<meta charset="utf-8" /> 
		<title>无标题文档</title> 
		<style> 
			.change{ height:300px; border:1px solid #000; margin:0 auto} 
			@media screen and (min-width: 1201px) { 
			.change {width: 1200px} 
			} 
			/* 设置了浏览器宽度不小于1201px时 change 显示1200px宽度 */ 
			@media screen and (max-width: 1400px) { 
			.change {width: 900px} 
			} 
			/* 设置了浏览器宽度不大于1200px时 change 显示900px宽度 */ 
			@media screen and (max-width: 900px) { 
			.change {width: 200px;} 
			} 
			/* 设置了浏览器宽度不大于900px时 change 显示200px宽度 */ 
			@media screen and (max-width: 500px) { 
			.change {width: 100px;} 
			} 
			/* 设置了浏览器宽度不大于500px时 change 显示100px宽度 */ 
		</style> 
	</head> 
	<body> 
		<div class="change">CSS实例:DIV宽度会随浏览器宽度变化,尝试改变浏览器宽度</div> 
	</body> 
</html> 

另外,可以根据实际使用的情况或者封装策略,可以考虑分成多个css文件的配置方式

<!-- 分辨率低于1280,采用test1.css样式表 -->
<link rel="stylesheet" media="screen and (max-device-width:1440px)" href="test1.css">
<!-- 分辨率高于1400,采用test2.css样式表 -->
<link rel="stylesheet" media="screen and (min-device-width:1920px)" href="test2.css">

总之上面两种方式都是对于适应各种分辨率的不同习惯写法,需要根据自己项目的封装规则自由选择。需要注意的是样式的排布顺序需要按照分辨率升序或者降序的顺序去设置,否则可能会出现设置之后并没有按照想象的效果去显示。

所周知,前端的移动端适配问题是个老生常谈的问题,面试中也是经常被问到,面试官经常是一句“你是怎么做移动端适配的”或者“谈谈你对移动端适配的理解”就让面试者感觉不知道该从什么地方下手去回答这个问题。手机市场日渐丰富的同时,给我们前端开发人员带来的网页内容自适应屏幕尺寸进行显示的问题也日渐凸显出来。

本文将针对移动端适配问题进行总结,总结一下各主流适配方案以及在主流框架中是怎么做适配的,希望通过本文能让读者在遇到移动端适配的面试问题时不再不知所措。

相关概念

要搞明白移动端适配问题,就要先搞明白屏幕、像素和视口三个概念。

一、屏幕

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 端不同,有三个视口:

  • 布局视口
  • 视觉视口
  • 理想视口
  1. 布局视口:布局视口是用来放置网页内容的区域。

一般移动设备的浏览器都默认定义一个虚拟的布局视口(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';

总结

本文中例举的适配方案是目前比较主流的适配方案,大家可以根据项目需求来使用不同的适配方案,也希望本文能够帮助到面试的同学在适配这方面的问题上不再不知所措,跟面试官交流的时候可以问有所答,畅所欲言。

是poetry,点击上方“关注”,每天为你分享前端进阶与个人精进干货。

一、为什么要做适配

  • 为了适应各种移动端设备,完美呈现应有的布局效果
  • 各个移动端设备,分辨率大小不一致,网页想铺满整个屏幕,并在各种分辨下等比缩放

二、适配方案

  • 固定高度,宽度百分比适配-布局非常均匀,适合百分比布局
  • 固定宽度,改变缩放比例适配-什么情况都可以
  • Rem适配
  • 像素比适配

三、单位

  • em根据元素自身的字体大小计算,元素自身 16px 1em=16px
  • Rem R -> root 根节点( html ) 根据html的字体大小计算其他元素尺寸

四、百分比适配(常用)

固定高度,宽度百分比适配

  • 根据设置的大小去设置高度,单位可以用px 百分比 auto
  • 常用Flex布局
  • 百分比宽度

640设计稿为例,在外层容器上设置最大以及最小的宽

#wrapper {
    max-width: 640px; /*设置设计稿的宽度*/
    min-width: 300px;
    margin: 0 auto;
}

后面的区块布局都用百分比,具体元素大小用px计算

  • 也就是宽度用百分比,高度用px
  • 高度以及图片不要定死,让它自动撑开

五、Rem适配(常用)

  • 根据屏幕的分辨率动态设置html的文字大小,达到等比缩放的功能
  • 保证html最终算出来的字体大小,不能小于12px
  • 在不同的移动端显示不同的元素比例效果
  • 如果htmlfont-size:20px的时候,那么此时的1rem=20px
  • 把设计图的宽度分成多少分之一,根据实际情况
  • rem做盒子的宽度,viewport缩放

head加入常见的meta属性

<meta name="format-detection" content="telephone=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!--这个是关键-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimum-scale=1.0">

把这段代码加入head中的script预先加载

// rem适配用这段代码动态计算html的font-size大小
(function(win) {
    var docEl=win.document.documentElement;
    var timer='';

    function changeRem() {
        var width=docEl.getBoundingClientRect().width;
        if (width > 750) { // 750是设计稿大小
            width=750;
        }
        var fontS=width / 10; // 把设备宽度十等分 1rem=10px
        docEl.style.fontSize=fontS + "px";
    }
    win.addEventListener("resize", function() {
        clearTimeout(timer);
        timer=setTimeout(changeRem, 30);
    }, false);
    win.addEventListener("pageshow", function(e) {
        if (e.persisted) { //清除缓存
            clearTimeout(timer);
            timer=setTimeout(changeRem, 30);
        }
    }, false);
    changeRem();
})(window)
  • 或者使用淘宝提供的库 https://github.com/amfe/lib-flexible

布局细节

  • 结构用section区块划分更语义化
  • 然后在body设置宽度
body {
    width: 10rem;
    margin: auto;
}

后面的区块都以百分比布局

<div class="wrapper">
   <header><header>
   <section><section>
   <section><section>
   <section><section>
   <section><section>
</div>
section,
header {
    width: 100%;
}

把视觉稿中的 px 转换成 rem

首先,目前日常工作当中,视觉设计师给到前端开发人员手中的视觉稿尺寸一般是基于 640px750px 以及 1125px 宽度为准。甚至为什么?大家应该懂的(考虑Retina屏)

假定设计稿的大小为750,那么我们则将整个图分成10等份来看。<html> 对应的 font-size75px

html{
    font-size: 75px;
}
  • 这样一来,对于视觉稿上的元素尺寸换算,只需要原始的 px值 除以 rem基准值 即可

那么,我们现在就可以比对设计稿,比如设计稿中,有一个div元素,宽度,高度都为20px,那么我们这样写即可(可以用 markman标准设计稿的元素大小)

div {
    height: 0.27rem; /*20/75*/
    width: 0.27rem;
}
  • 动态计算的rem最后会帮我们动态计算元素在不同屏幕下的宽高
  • 对于设计稿上的每个元素的尺寸在设计稿大小已知的时候,我们需要测量出,然后在用测量的宽高除以设计稿750的十分之一也就是75,得到我们想要的rem。而rem是根据屏幕动态变化的,也就达到了适配的效果。也就是同一套设计稿运用在不同的设备上。

比如当我们切换到320设备大小的时候,这时候1rem=32px; div的像素实际是0.27*32=8.64px 0.27是我们在已知设计稿是750的情况下计算出来的,rem用来动态计算而已

  • 对于margin padding line-height width height使用rem计算

如何快速计算

在实际生产当中,如果每一次计算 px 转换 rem ,或许会觉得非常麻烦

  • `CSSREM` 是一个CSSpx 值转 rem 值的Sublime Text3自动完成插件
  • 插件效果

[图片上传失败…(image-4f244b-1545535128364)]

插件使用方法

  • 安装
  • 下载本项目,比如:git clone https://github.com/flashlizi/cssrem
  • 进入packages目录:Sublime Text -> Preferences -> Browse Packages
  • 复制下载的cssrem目录到刚才的packges目录里。
  • 重启Sublime Text
  • 配置参数
  • 参数配置文件:Sublime Text -> Preferences -> Package Settings -> cssrem
  • px_to_rem - pxrem的单位比例,默认为40【根据设计稿来设置,如设计稿750,我们取十分之一即75】。
  • max_rem_fraction_length - pxrem的小数部分的最大长度。默认为6
  • available_file_types - 启用此插件的文件类型。默认为:[".css", ".less", ".sass"]。

文字适配的解决方案

  • 对于一些标题性的文字,我们依然可以用rem。让他随着屏幕来进行缩放,因为标题性文字一般较大,而较大的文字,点阵对其影响就越小。这样,即使出现奇怪的尺寸,也能够让字体得到很好的渲染。
  • 对于一些正文内容的文字(即站在使用者的角度,你不希望他进行缩放的文字)。我们采用px来进行处理

六、缩放比适配

固定宽度,改变缩放比例适配

  • 设计图的宽度就是网页显示的宽度
  • 改变视口的缩放比例
  • 页面宽度固定死
// 缩放比例适配方案--用这个代码 
var width=window.screen.width,
    fixedW=320, //设计稿宽度的一半
    scale=width / fixedW, // 缩放比例
    meta=document.createElement('meta'),
    metaAttr={
        name : 'viewport',
        content : 'width='+fixedW+', initial-scale='+scale+', maximum-scale='+scale+', user-scalable=0'
    };
    for (var key in metaAttr) {
        meta[key]=metaAttr[key];
    }
    document.head.appendChild(meta);

七、像素比适配

  • window.devicePixelRatio
  • 物理像素是手机屏幕分辨率
  • 独立像素 指css像素 屏幕宽度
  • 像素比=物理像素 / css宽度
  • 获取设备的像素比 window.devicePixelRatio

八、小结

关于移动端布局方案有很多,rem和百分比运用最多的

作者介绍:poetry,专注前端进阶写作与个人精进干货,目前在上市公司负责小程序等相关的研发。