文章

rem 适配

1.老版常规做法

1.1 viewport 缩放

以最小的iphone4/5的宽度(320px)为基准,还原视觉稿

  1. <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0" />

然后对不同屏幕分辨率的手机进行简单粗暴的等比例缩放设置,例如 iphone8(375px) initial-scale = 375/320 = 1.8

  1. <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.8" />

initial-scale越来越大,页面内容也就被拉伸的越厉害,导致页面内容会变得模糊

1.2固定宽度进行留白

把页面固定死宽度,多余的宽度进行居中留白

1.3响应式布局

通过媒体查询根据不同的屏幕分辨率来进行适配,问题在于

  • 屏幕分辨率区间:区间内无法进行区分,无法实现100%兼容,一般是用主流分辨率来进行划分
  • 额外的工作量:响应式布局的工作都是需要开发者去实现的,带来了额外的开放量
  • 不适合功能复杂的页面:响应式一般适合于资讯类页面,功能复杂的网站对于页面的整体排版和样式要求较高(特别是pc和h5)

2.rem

当我们指定一个元素的font-size为2rem的时候,也就是说这个元素的字体大小为根元素字体大小的两倍。如果html的font-size为12px,那么这个2rem的font-size就是24px,同理当该元素为3rem时,那么实际font-size就是36px.

  1. html {font-size:12px}
  2. h1 {font-size:2rem} //24px
  3. p {font-size:1.5rem} //18px
  4. html {font-size:16px}
  5. h1 {font-size:2rem} //32px

只要我们根据不同屏幕设定好根元素的font-size,其它已经使用了rem 单位的元素就会自适应显示相应的尺寸。

单位 定义 特点
rem font size of the root element 以根元素字体大小为基准
em font size of the element 以父元素字体大小为基准

3.rem计算

3.1js计算

通过js读取屏幕宽度,然后根据宽度计算出对应的尺寸并设置根元素的font-size

  1. const oHtml = document.getElementsByTagName('html')[0]
  2. const width = oHtml.clientWidth
  3. //320px的屏幕基准像素为12px
  4. oHtml.style.fontSize = 12*(width/320) + 'px'

这样iphone8(375px)下html的font-size就是14.0625px,iphone8p下font-size就是15.525px。

使用js来获取屏幕宽度的好处在于可以100%适配所有的机型宽度,因为其元素的基准尺寸是直接算出来的,既然是js代码,为了避免造成因为动态设置元素的font-size而造成页面抖动,一般这部分代码我们放在header底部加载,并内联到html文档里面。

3.2媒体查询

  1. @media screen and (min-width: 375px){
  2. html {
  3. font-size: 14.0625px;
  4. }
  5. }
  6. @media screen and (min-width: 360px){
  7. html {
  8. font-size: 13.5px;
  9. }
  10. }
  11. @media screen and (min-width: 320px){
  12. html {
  13. font-size: 12px;
  14. }
  15. }
  16. html {
  17. font-size: 16px;
  18. }

4.rem存在的问题

举个例子:小说软件显示的字号是不变的。

iOS与Android平台的适配方式背后隐藏的设计哲学是这样的:阅读文字时,可读性较好的文字字号行距等绝对尺寸数值组合与文字所在媒介的绝对尺寸关系不大。(可以这样简单理解:A4大小的报纸和A3大小甚至更大的报纸,舒适的阅读字号绝对尺寸是一样的,因为他们都需要拿在手里阅读,在手机也是上同理);在看图片视频时,图片、视频的比例应该是固定的,不应该出现拉伸变形的情况。而rem用在字号时,使字号在不同屏幕上的绝对尺寸不一致,违背了设计哲学。

5.工程应用

5.1 px转rem工具

5.2 mixin

5.3工程化构建

webpack px-to-rem-loader

实现简版初始化根元素得字体大小

页面开头引用这段代码,用于动态计算font-size

  1. (假设你需要的1rem = 20px)
  2. (function () {
  3. var html = document.documentElement;
  4. function onWindowResize() {
  5. html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
  6. }
  7. window.addEventListener('resize', onWindowResize);
  8. onWindowResize();
  9. })();
  10. <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-sacle=1.0, maximum-scale=1.0, user-scalable=no" />
  • document.documentElement:获取document的根元素
  • html.getBoundingClientRect().width:获取html的宽度(窗口的宽度)
  • 监听window的resize事件