web移动端UI适配之rem

移动端适配大致两种,一种是百分比还有一种就是rem,这里就说说rem适配要怎么做,原理是什么。先说说为什么要做适配吧。

为何要适配?

众所周知,手机屏幕的尺寸是五花八门的,像素密度也是不一样的。同样是宽度5cm的屏幕,有的手机是720px,有的手机是1080px。

那么假设设计师有个设计稿,宽度是720px的,设计稿里有张图,这张图的宽度也是720px。如果我们直接在代码里写这张图的宽度为720px,那我们在720px的手机上看则是正常的,这里我们用一个div做演示


720px屏幕

但是当用户的手机屏幕宽度有1080px的时候呢?看起来就会像这样


1080px屏幕

很显然这跟预期的不一样,所以我们需要div的尺寸跟随实际屏幕的宽度进行缩放。这时,我们的rem就刚好满足需求。

rem(font size of the root element)是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。看到rem大家一定会想起em单位,em(font size of the element)是指相对于父元素的字体大小的单位。它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。

简单来说,我们设定html元素的font-size等于100px时,1rem就等于100px。1 rem = 1 font-size

所以我们只需要获取屏幕的宽度,然后根据宽度和设计稿的比例来计算html的font-size,并设置上去。
在写代码的时候,就用rem代替px,这样就可以使div的尺寸根据html的font-size缩放了

如何计算font-size?

我们来做几个设定

  • 设计稿宽度为750px
  • 设计稿中有一个div,宽度也是750px
  • 理想状态(实际屏幕宽度也是750px)下html的font-size是100px,即1rem=100px

那么,我们先手动写一下理想状态

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>rem适配</title>
    
</head>
<style>
    body {
        margin: 0;
        font-size: 16px;;
    }
    html {
        font-size: 100px;
    }
</style>
<body>
    <div style="width: 7.5rem;background: yellow;">
        750px/100 = 7.5rem div
    </div>
</body>
</html>

一定要写body下的font-size=16px,或者你需要的,不然body元素下的文字默认大小就会继承html下的100px,那样的话,字体就太大了。

好了,来看效果


750px下的7.5rem

一切正常,我们来把屏幕像素稍微调大一点,把屏幕宽度调成900。


900px下的7.5rem

由于我们没有动态调节html的font-size,所以div的宽度没有跟随变化。那么就来计算一下。

先算出100px是设计稿的多少倍,然后再乘以实际屏幕宽度,就能算出缩放后的font-size了。
100/750*900 = 120px
现在把120设置上去

html {
     font-size: 120px;
}

搞定~

900px下的7.5rem

好了,rem适配的基本原理你已经知道了,我们开始编码。
新建一个flexible.js

// designWidth:设计稿的实际宽度值,需要根据实际设置
// maxWidth:支持缩放的最大屏幕宽度值,当屏幕宽度超过此值则按最大值进行计算,需要根据实际设置
// 这段js的最后面有两个参数记得要设置,一个为设计稿实际宽度,一个为支持缩放的最大屏幕宽度值,例如设计稿为750,最大宽度为750,则为(750,750)
(function(designWidth, maxWidth) {
    var doc = document
    var win = window
    var docEl = doc.documentElement
    var remStyle = document.createElement('style') // 创建一个style标签,用于写html样式
    var tid //timeout句柄
  
    // 计算rem的值,即1rem等于多少px
    function refreshRem() {
      var width = docEl.getBoundingClientRect().width // 获取屏幕宽度
      maxWidth = maxWidth || 750 // 当没写maxWidth时,默认maxWidth=750
      // 当屏幕宽度超过最大缩放的值,则按最大值处理,不能无限缩放,那样会变得很大,很丑
      if (width > maxWidth) {
        width = maxWidth
      }
      // 计算html的font-size
      var rem = 100 / designWidth * width
      remStyle.innerHTML = 'html{font-size:' + rem + 'px;}'
    }
  
    // 将style标签插入到文档
    if (docEl.firstElementChild) {
      docEl.firstElementChild.appendChild(remStyle)
    } else {
      var wrap = doc.createElement('div')
      wrap.appendChild(remStyle)
      doc.write(wrap.innerHTML)
      wrap = null
    }
    // 要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
    refreshRem()
  
    win.addEventListener('resize', function() {
      clearTimeout(tid) // 防止执行两次
      tid = setTimeout(refreshRem, 300)
    }, false)
  
    win.addEventListener('pageshow', function(e) {
      if (e.persisted) { // 浏览器后退的时候重新计算
        clearTimeout(tid)
        tid = setTimeout(refreshRem, 300)
      }
    }, false)
  
    // 设定body的默认字体大小,如果不设置,将集成html的字体大小,而我们设置的100,so...
    if (doc.readyState === 'complete') {
      doc.body.style.fontSize = '16px'
    } else {
      doc.addEventListener('DOMContentLoaded', function(e) {
        doc.body.style.fontSize = '16px'
      }, false)
    }
  })(750, 750)
// 这里我们输入设计稿750px,支持的最大屏幕宽度也是750px。

可能有同学会问,为什么只有750px,现在手机都是1080px了。

其实浏览器返回给js和css的px都是抽象的,是根据真实像素和ppi计算出来的,像我的小米8,1080px宽度,js获取的屏幕宽度也只有393px

并且一定要在head元素里写 <meta name="viewport" content="width=device-width, initial-scale=1.0">
关于viewport是啥,可以参阅 https://blog.csdn.net/lamanchas/article/details/78473249

最后,我们只需要在html中引用此文件即可,也可以用es6的方式引用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>rem适配</title>
    <script src="./flexible.js" type="text/javascript"></script>
    <style>
    body {
        margin: 0;
    }
    </style>
</head>
<body>
    <div style="width: 7.5rem;background: yellow;">
        750px/100 = 7.5rem div
    </div>
</body>
<script>
</script>
</html>

最后效果

25.gif
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容

  • 说到前端页面的布局方案,可以从远古时代的Table布局说起,然后来到 DIV+CSS布局,之后有了Float布局,...
    841只阅读 1,448评论 1 3
  • 了解真实的『REM』手机屏幕适配rem 作为一个低调的长度单位,由于手机端网页的兴起,在屏幕适配中得到重用。 使用...
    张宪宇阅读 2,239评论 0 5
  • 在移动互联网快速发展的今天,手机的种类和尺寸越来越多,作为前端的小伙伴们可能会越来越头疼,但又不得不去适配一款又一...
    keenjaan阅读 26,816评论 9 86
  • 题外话 突然被要求教学妹怎么做移动端适配的问题,上一次我写移动端的东西过去好久了,于是又面向百度了一波,网上感觉还...
    郑虎三阅读 572评论 0 10
  • 我们总是焦虑,抱怨生活的不公平,觉得自己就是那个最失败的人。可你真的认真对比过吗?你可能不知道,有多少人正羡慕着你...
    枫河阅读 55评论 0 1