【移动端布局】2 - 适配方法:百分比适配、viewport缩放适配、dpr缩放适配、rem适配、vw适配

关于适配

适配用来做布局的,移动端比较麻烦-设备太多,尺寸也不一样;而且设计师设计的尺寸 和我们切图的尺寸也不一样;

适配:在不同尺寸的手机设备上,页面相对性的达到合理的展示(自适应)或者保持统一效果的等比缩放(看起来差不多)

适配的元素:

  1. 字体
  2. 宽高
  3. 间距
  4. 图像(图标、图片)

适配的方法:

  1. 百分比适配
  2. viewport缩放
  3. DPR缩放
  4. rem适配 - rem是单位,主流适配
  5. vw、vh适配 - vw、vh 也是单位

手机分辨率,ppi等的查询1
手机分辨率,ppi等的查询2
手机分辨率,ppi等的查询3


1、百分比 适配

根据父级算百分比,需配合其它布局使用

  1. 根据父级的宽度绝对自己的宽度,宽度好算,高度没法算;
  2. 所以建议:高度不变,宽度变化的时候 用 百分比
  3. 百分比布局案例:360拉钩

2、viewport缩放适配

viewport缩放适配 把所有机型的css像素设置成一致的:如iphone6是375,6p是414, 我们通过缩放,把所有设备的css像素都改成375

  1. viewport需要通过js动态的设置(不能直接把device的值设置成数值)

  2. 通过设置比例(初始比例以及缩放比例),把宽度缩放成一致的

  3. 公式
    缩放比 = css像素 / 375;
    css像素-- 当前的css像素值 ,没有缩放的时候viewport的值,也就是html的宽度
    375 – 目标要缩放到的像素值

  4. 缺点:任何宽度都缩放成375了,大于750的屏幕会模糊;小数点会有误差

<script>   //放在head标签里,页面加载之前先设置页面宽度
	(function(){
		//获取css像素(viewport没有缩放前的css像素,如iphone6是375,6p是414, 我们通过缩放,把所有设备的css像素都改成375)
		var curWidth=document.documentElement.clientWidth;   //方式1:没有缩放的时候viewport的值,也就是html的宽度
		var curWidth=window.innerWidth;      //方式2:没有缩放的时候viewport的值,也就是html的宽度
		var curWidth=window.screen.width;   //方式3:没有缩放的时候viewport的值,也就是html的宽度
		var curWidth = document.documentElement.getBoundingClientRect().width;	//取宽度还可以用这种方式

		var targetWidth=375;    //375是iphone6的css像素,都向他看起
		var scale=curWidth/targetWidth;   //计算得到缩放比
		console.log(scale); 

		var view=document.getElementById('view');

		view.content='initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'';  //要缩放就不能给width=device-width了,要把初始缩放,最小缩放和最大缩放都改了
	})();
</script>

3、DPR缩放适配

DPR缩放适配根据dpr的值,把视口进行缩放,缩放到物理像素,也就是把css像素的值设置成物理像素,让所有的设备都变成一个css像素对应一个设备像素,也就是1px = 1pt ,1比1的关系;

  • 如:iphone6的css像素是375,我们通过dpr适配把css像素的值变成 375 2 (dpr) = 750的大小。此时1px = 1pt
  • 这样缩放后视口变成了750 后,切图的时候就按设计稿来切图 就可以了,但是div还是不能是像素来写,不然 6 和 6p的尺寸不一样,div还是写一样的尺寸,肯定不行,所以还要结合用 百分比
  • js动态的创建meta标签
<script>
	(function(){
		/*
			375*2	-> 750 
			320*2	-> 640

			375/?=750	=> 375/750=2
			1/dpr  -- 缩放比

			320/scale=640	=> 	scale=320/640	1/2
		 */

		var meta=document.querySelector('meta[name="viewport"]');   //c3选择器 得到meta标签
		var scale=1/window.devicePixelRatio;   //计算缩放比 = 1 / 像素比dpr

		if(!meta){   //如果页面里没有name=viewport的meta标签
			//这个条件成立说明用户没有写meta标签,我需要创建一个
			meta=document.createElement('meta');
			meta.name='viewport';
			meta.content='width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'';    //width  和 initial-scale里选大的,肯定是initial-scale大 所以放width=device-width 没关系
			document.head.appendChild(meta);
		}else{   //如果有
			meta.setAttribute('content','width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'');
		}
	})();
</script>

4、rem适配

rem 和px一样就是一个单位;
em 和 rem 最终都会被转成px;

4.1 em 和 rem的区别

还有一个单位叫em,em 和 rem的区别:
-----------------em------------- :

  1. 作为font-size的单位时,其代表父元素的字体大小
.em{
	font-size: 10px;
}
.em p{
	font-size: 2em;	/* em 是font-size的单位,em代表其父元素的字体大小10px,1em=10px */   /*所以这里字体大小是20px*/
}
  1. 作为其他属性单位时,代表自身字体大小
.em{
	font-size: 30px;

	border: 1px solid #000;
	width: 10em;	/* em是其他属性的单位时,m代表自身元素的字体大小30px,1em=30px */   /*所以这里width是300px*/
	height: 10em;
}

问题:
1、chrom下有最小字体限制,必需为12px,所以em值不能小于12
2、如果两个一样的元素,但是里面字体不一样,那就不能统一设置了。或者元素字体变化了,就又要统一设置一遍

----------rem -----------
rem 是 CSS3新增的一个相对单位,是相对于根元素html字体大小

rem 中 r 就是 root
html{font-size:20px} 2rem=40px

判断屏幕的宽度(css像素),根据屏幕宽度设定不同的html字体大小,然后所有和尺寸相关的都用rem做单位,这个所有的尺寸都和屏幕宽度有关联了;


4.2 rem适配原理

rem适配的原理:把所有的设备都分成相同的若干份,再计算元素宽度所占的份数,也是栅格化的原理

详细说:把屏幕实际的宽度(css像素)分成相同的若干份,每份就是1rem,再计算元素设计稿里的宽所占的份数(也就是占几个rem),最后得到 元素适配的宽度 =元素所占的列数*1rem,然后把1rem的值 赋给html的字体大小;

1、元素适配的宽度(算出来的)
=元素所占的列数一列的宽
=元素所占的列数
1rem

  1. 一列的宽度 = 屏幕实际的宽度 / 列数
    一列的宽度(一列的宽度就是1rem)= 屏幕实际的宽度(css像素)/ 列数 (分多少列自己根据实际情况给的)
  2. 元素实际占的列数 =元素设计稿里的宽 / 一列的宽(1rem)
  3. 元素适配的宽度 =元素所占的列数 * 一列的宽(1rem)
  4. 然后把1rem的值 赋给html的字体大小
 html{
	font-size:屏幕实际的宽度(css像素)/ 列数
} 
设置html字体的方式: js设置  或者  媒体查询设置

4.3 js动态设置html字体大小 - 笨方法,要自己算元素占几个rem

  1. 一列的宽度=屏幕实际的宽度(css像素)/列数
  2. 元素实际占的列数=元素设计稿里的宽/1rem
  3. 元素适配的宽度=元素所占的列数*1rem

------------真正切图时候的方法:-------------
4. 算rem,还是根据设备实际的css像素算
5. 量出一个元素在设计稿里的尺寸,拿这个尺寸除以DPR值后,再去换算占几个rem:元素实际占的列数=元素设计稿里的宽/1rem
6. 元素适配的宽度=元素所占的列数*1rem

img{
	width: 16rem;	/* 640/2=320/20=16rem */
}

如上,比如在iphone5中(css像素是320px,分了16列,一列是20px 也就是1rem=20px),设计稿给了一个640px的图片, 我们拿640px/dpr =320px 后,在算图片占了几个rem (320/20=16rem)

  1. 实际中我们是要高清显示的,要高清,所以设计稿的尺寸一般是 实际的像素尺寸 * dpr ,也就是 按物理像素给的尺寸;
  2. 但是我们求rem的时候是按css像素算的,所以算div占几个rem的时候,需要把div 由物理像素 换成css像素,也就是拿设计稿尺寸/dpr 后 ,再算占几个rem
<script>
	(function(){
		var html=document.documentElement;	//获取html
		var clientWidth=html.clientWidth;		//css像素,屏幕实际宽度
		
		html.style.fontSize=clientWidth/16+'px';	//把屏幕分成了16列,以iphone5为例得出一个列1rem的值为整数,把这个值赋给html元素
	})();


	//eg:iphone5
	//1rem= 320px/16 = 20px;		一列的宽度
	//80/1rem=80/20=4;	80是元素的宽度元素实际占的列数
	//4*1rem=4rem;		元素适配的宽度
</script>

4.4 js动态设置html字体大小 - rem的最优写法!!!

按照如下的写法:我们适配的时候,例如设计稿是css像素*dpr给的,我们只需要 设计稿尺寸/100即可,就是rem的列数,非常方便

<script>
	(function(doc, win, designWidth) {
		const html = doc.documentElement;   //获取根节点html
		//const dpr = win.devicePixelRatio;	//dpr
		
		function refreshRem(){  //不用用es6的箭头函数,会有问题,ios9 不支持es6
			const clientWidth = html.clientWidth;
			if (clientWidth >= designWidth) { //给宽度一个最大值,如果设备的宽度已经超过设计稿的尺寸了,统一按一个值去算(传的第三个参数)
				html.style.fontSize = '100px';
			} else {
				//html.style.fontSize= 16 * clientWidth / 375 + 'px';    //方法1:这么写的目的是为了找一个基准点,就是iphone6,因为iphone6的用户最多,且dpr为2
				html.style.fontSize = 100 * (clientWidth / designWidth) + 'px';   //方法2:这样写最优,这样切图的时候,换算的时候简单写,不用除dpr了,量的div的宽度/100就可以了
				// 按iphone6算:html的字体大小是50,算的时候假如div设计稿 是200 ,则要200/dpr/50 = 200 /100 ,这样算的时候直接拿设计稿挪两个小数点就行了
			}
		};
		
		//dom加载完的一个事件,和window.onload不一样
		doc.addEventListener('DOMContentLoaded', refreshRem);
	})(document, window, 750);   //这里传的实参,750px是设计稿尺寸,我们按iphone6为基准算
</script>
可以不看----关于按iphone6为基准算:16是iphone6的字体大小 ,这样可以使得 其他手机可以按自己的屏幕大小得到不同的rem
16 * clientWidth / 375 
	=> clientWidth / 375 * 16 
	=> clientWidth / (375 / 16)

//这么写的目的是为了找一个基准点,就是iphone6,

320 / (375 / 16) = 13.653;	iphone5	
375 / (375 / 16) = 16;		iphone6
414 / (375 / 16) = 17.664;	iphone6 p

4.5 媒体查询设置html字体大小

媒体查询是css3的知识点,可以检测当前屏幕的宽度和设备类型;-- 用的不多
缺点: 在范围区间内,字体大小是不变的, 如果要宽度改变一点都变化的话要用js

<style>
html {
	font-size: 50px
}

body {
	font-size: 24px
}

@media screen and (min-width: 320px) {  /*手动添加设备尺寸范围:用min-width  和 max-width 写范围*/
	html {
		font-size:21.33px    /*像这个例子是按15份分的,字体的大小有人赞成用px,但是rem 也是可以的,差别不大*/
	}

	body {
		font-size: 12px
	}
}
/*等等其他范围...*/
</style>

5、vw适配

发布了57 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Eva3288/article/details/104864704