文章目录
- 关于适配
- 1、百分比 适配
- 2、viewport缩放适配
- 3、DPR缩放适配
- 4、rem适配
- 4.1 em 和 rem的区别
- 4.2 rem适配原理
- 4.3 js动态设置html字体大小 - 笨方法,要自己算元素占几个rem
- 4.4 js动态设置html字体大小 - `rem的最优写法`!!!
- 4.5 媒体查询设置html字体大小
- 5、vw适配
关于适配
适配用来做布局的,移动端比较麻烦-设备太多,尺寸也不一样;而且设计师设计的尺寸 和我们切图的尺寸也不一样;
适配:在不同尺寸的手机设备上,页面相对性的达到合理的展示(自适应)或者保持统一效果的等比缩放(看起来差不多)
适配的元素:
- 字体
- 宽高
- 间距
- 图像(图标、图片)
适配的方法:
- 百分比适配
- viewport缩放
- DPR缩放
- rem适配 - rem是单位,主流适配
- vw、vh适配 - vw、vh 也是单位
手机分辨率,ppi等的查询1
手机分辨率,ppi等的查询2
手机分辨率,ppi等的查询3
1、百分比 适配
根据父级算百分比,需配合其它布局使用
- 根据父级的宽度绝对自己的宽度,宽度好算,高度没法算;
- 所以建议:高度不变,宽度变化的时候 用 百分比;
- 百分比布局案例:360 、 拉钩
2、viewport缩放适配
viewport缩放适配 把所有机型的css像素设置成一致的:如iphone6是375,6p是414, 我们通过缩放,把所有设备的css像素都改成375
-
viewport需要通过js动态的设置(不能直接把device的值设置成数值)
-
通过设置比例(初始比例以及缩放比例),把宽度缩放成一致的
-
公式
缩放比 = css像素 / 375;
css像素-- 当前的css像素值 ,没有缩放的时候viewport的值,也就是html的宽度
375 – 目标要缩放到的像素值 -
缺点:任何宽度都缩放成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------------- :
- 作为font-size的单位时,其代表父元素的字体大小,
.em{
font-size: 10px;
}
.em p{
font-size: 2em; /* em 是font-size的单位,em代表其父元素的字体大小10px,1em=10px */ /*所以这里字体大小是20px*/
}
- 作为其他属性单位时,代表自身字体大小
.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
- 一列的宽度 = 屏幕实际的宽度 / 列数
一列的宽度(一列的宽度就是1rem)= 屏幕实际的宽度(css像素)/ 列数 (分多少列自己根据实际情况给的) - 元素实际占的列数 =元素设计稿里的宽 / 一列的宽(1rem)
- 元素适配的宽度 =元素所占的列数 * 一列的宽(1rem)
- 然后把1rem的值 赋给html的字体大小
html{
font-size:屏幕实际的宽度(css像素)/ 列数
}
设置html字体的方式: js设置 或者 媒体查询设置
4.3 js动态设置html字体大小 - 笨方法,要自己算元素占几个rem
- 一列的宽度=屏幕实际的宽度(css像素)/列数
- 元素实际占的列数=元素设计稿里的宽/1rem
- 元素适配的宽度=元素所占的列数*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)
- 实际中我们是要高清显示的,要高清,所以设计稿的尺寸一般是 实际的像素尺寸 * dpr ,也就是 按物理像素给的尺寸;
- 但是我们求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>