移动端适配:动态设置html元素的font-size(页面使用rem做单位)

一、前言:

首先我们要了解的知识点:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值