一、前言:
首先我们要了解的知识点:
1.物理像素(physical pixel)
我们看到的每个屏幕都是由一颗颗我们肉眼难以看到的小颗粒(物理像素)组成的。
2.逻辑像素(设备独立像素(density-independent pixel))
是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素)。
3.设备的像素比(device pixel ratio)简称DPR
它的数值体现了物理像素和逻辑像素之间的关系,用公式可以计算出该设备的DPR的大小:
DPR = 物理像素 / 逻辑像素
那么了解了上面这些概念,就可以知道,为什么css在pc上写着font-size=12px;但是换到手机上却变小了?因为手机端的DPR变大了。
没错,我们在电脑屏幕上的DPR是1,但是手机却不同,可能是它可能是2,也可能是3。
获取设备DPR的方法还是有的:
1.在JavaScript中,通过window.devicePixelRatio来获取
2.在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同DPR的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。
二、页面适配开发
1、设置页面的viewport视口
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
2、我们以iPhone6设计稿来进行移动端的开发(设计稿是750px)
那么我们得到的deviceWidth = 375px; 为了方便在开发的时候量尺寸好算,我们设置html的font-size为50px。
那么本来根据设计稿量出来的div是80px的话我们要先除以2,得到实际的宽度px,然后要转换为rem,我们还要除以html的font-size,即再除以50,即可得到单位rem的数值。
也就是说:拿到一个iPhone6设计图,量到的px像素值来除以100,那么得到的值就是多少rem。
deviceWidth = 320,font-size = 320 / 7.5 = 42.6667px
deviceWidth = 375,font-size = 375 / 7.5 = 50px
deviceWidth = 414,font-size = 414 / 7.5 = 55.2px
deviceWidth = 500,font-size = 500 / 7.5 = 66.6667px
这个deviceWidth就是viewport设置中的那个device-width。
(设置html的font-size的值为多少其实就是为了方便计算,如果你的设计稿是iPhone4,那么html的font-size = 320 / 6.4 = 50px方便计算)
动态设置HTML元素的font-size代码如下:
var html = document.documentElement; //获取到html元素
var hWidth = html.getBoundingClientRect().width;//获取到html的宽度
if(hWidth > 640) hWidth = 640; // 当hWidth大于640时,则物理分辨率大于1280(这就看设备的devicePixelRatio这个值了),应该去访问pc网站了
html.style.fontSize = hWidth/7.5 + "px"; //设置HTML的字体大小 font-size = 50px,1rem = 50px
3、如果页面的字体不想使用rem作为单位,那么就使用媒体查询来设置body的font-size。
@media screen and (min-width: 320px) {
body {font-size: 14px;}
}
@media screen and (min-width: 360px) {
body {font-size: 16px;}
}
@media screen and (min-width: 400px) {
body {font-size: 18px;}
}
@media screen and (min-width: 440px) {
body {font-size: 20px;}
}
@media screen and (min-width: 480px) {
body {font-size: 22px;}
}
@media screen and (min-width: 640px) and (max-width: 640px) {
body {font-size: 28px;}
}
4、各屏幕的rem适配(终极方案)------- sass语法
$baseDevice: 750; // 默认iphone6设计稿
$device: $baseDevice / 2; // 375 ,iphone6设备宽度
$baseFontSize: 100px;
@function px2rem($px, $base-font-size: $baseDevice / $device * $baseFontSize) {
// unitless() 函数只是用来判断一个值是否带有单位,如果不带单位返回的值为 true,带单位返回的值为 false
// unit() 函数主要是用来获取一个值所使用的单位,碰到复杂的计算时,其能根据运算得到一个“多单位组合”的值,不过只充许乘、除运算
@if (unitless($px)) {
@warn 'Assuming #{$px} to be in pixels';
@return px2rem($px + 0px)
}
@else if (unit($px) == rem) {
@return $px
}
@return ($px / $base-font-size) * 1rem
}
html {
font-size: $baseFontSize;
}
@media screen and (min-width: 320px) {
html {
font-size: (320 / $device) * $baseFontSize;
}
}
@media screen and (min-width: 360px) {
html {
font-size: (360 / $device) * $baseFontSize; // 96px
}
}
@media screen and (min-width: 375px) {
html {
font-size: (375 / $device) * $baseFontSize; // 100px
}
}
@media screen and (min-width: 480px) {
html {
font-size: (480 / $device) * $baseFontSize; // 128px
}
}
@media screen and (min-width: 640px) {
html {
font-size: (640 / $device) * $baseFontSize;
}
}
@media screen and (min-width: 750px) {
html {
font-size: (750 / $device) * $baseFontSize;
}
}
// 示例使用
div {
font-size: px2rem(28px); // 750px的设计稿量出来是多少px就直接扔进去自动换算为rem
}
5、各屏幕的rem适配(终极方案)------- less语法
注意:开发的时候要区分好设计稿是iPhone6的二倍还是一倍,如果是二倍(750px),那么再计算rem的时候要记得除以2。
下面的计算是根据一倍设计稿(375px)。
// 默认iphone6两倍设计稿
@baseDevice: 750;
// 375 ,iphone6设备宽度
@device: @baseDevice / 2;
@baseFontSize: 50px;
/**
px转rem (混入的方式转换)
@name: css属性名
@px: 不带单位的px值
使用方式:
.px2rem(font-size, 14);
*/
.px2rem(@name, @px){
@{name}: @px / @baseFontSize * 1rem;
}
/**
px转rem (自定义函数的方式转换)
使用方式(可加单位、也可不加单位):
font-size: ~`px2rem("14px")`;
font-size: ~`px2rem(14)`; // 推荐使用
margin-left: ~`px2rem(-20)`; // 负数的使用
*/
.remMixin() {
@functions: ~`(function() {
var baseFontSize = 50;
function convert(size) {
return typeof size === 'string' ?
+size.replace('px', '') : size;
}
this.px2rem = function(size) {
return convert(size) / baseFontSize + 'rem';
}
})()`;
}
.remMixin();
html {
font-size: @baseFontSize;
}
@media screen and (min-width: 320px) {
html {
font-size: (320 / @device) * @baseFontSize;
}
}
@media screen and (min-width: 360px) {
html {
font-size: (360 / @device) * @baseFontSize; // 47px
}
}
@media screen and (min-width: 375px) {
html {
font-size: (375 / @device) * @baseFontSize; // 50px
}
}
@media screen and (min-width: 480px) {
html {
font-size: (480 / @device) * @baseFontSize; // 64px
}
}
@media screen and (min-width: 640px) {
html {
font-size: (640 / @device) * @baseFontSize;
}
}
@media screen and (min-width: 750px) {
html {
font-size: (750 / @device) * @baseFontSize;
}
}
6、淘宝的H5移动端适配方案flexible.js
学习链接: https://github.com/amfe/article/issues/17#
————————————————————————————————————
参考原文:
https://segmentfault.com/a/1190000004189237
https://www.cnblogs.com/axl234/p/5156956.html