美文网首页vue.jsVue.jsVue移动端
06、手把手教Vue--移动webapp适配方案--rem

06、手把手教Vue--移动webapp适配方案--rem

作者: TigerChain | 来源:发表于2018-09-19 22:07 被阅读330次

    PS:转载请注明出处
    作者: TigerChain
    地址: https://www.jianshu.com/p/443c6704d8d8
    本文出自 TigerChain 简书 手把手教 Vue 系列

    大纲

    教程简介

    • 1、阅读对象
      本篇教程适合新手阅读,老手直接略过
    • 2、教程难度
      初级,本人水平有限,文章内容难免会出现问题,如果有问题欢迎指出,谢谢
    • 3、Demo 地址:https://github.com/githubchen001/vue-lesson 请看 05、移动webapp适配--rem 这一节

    正文

    一、media query「媒体查询」

    在聊 rem 之前,我们先看看什么是 media query?

    为了适配多种屏幕大到电脑,小到手机等, css3 中有了多媒体查询这个功能「是继承 css2 多媒体类型的思想」,通过 media query 就可以做响应式的开发

    1、media query 的作用

    • 可以检测 viewport(视窗) 的宽度与高度
    • 可以检测设备的宽度与高度
    • 可以检测设备的分辨率

    2、media query 的语法

    @media not|only mediatype and (expressions) {
        CSS 代码...;
    }
    

    我们可以看到 media query 由四部分组成

    • 1、关键字:@media
    • 2、操作符:not|only|all 「默认不写就是 all」
    • 3、媒体类型:mediatype
    • 4、表达式:expressions

    这里的媒体类型有以下几种:

    描述
    all 用于所有多媒体类型设备
    print 用于打印机
    screen 用于电脑屏幕,平板,智能手机等。
    speech 用于屏幕阅读器

    一般情况下我们使用 screen 的媒体类型是最多的

    举个例子

    我们想让在屏幕尺寸大于 375px 的设备上让 class 为 div1 的背景显示成红色,media query 哪下定义

    @media screen and (min-device-width : 375px){
        .div1 {
            background-color:red;
        }
    }
    

    我们可以针对不同的设备宽度来设置不同的样式 ,这样就达到了响应式布局的效果,现在我们来一个例子说明吧

    3、demo 验证 media query

    效果如下

    media query 效果

    从上面的效果图我们可以看到,我们针对不同屏幕宽度就会显示不同的效果,这就是响应式布局,下面我们使用 media query 来实现这一效果

    撸码实现上述效果

    <!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>media-query</title>
      <!-- 重置默认的 css 样式 ,类似于 reset.css -->
      <link rel="stylesheet" href="../css/normalize.css">
      <!-- https://necolas.github.io/normalize.css/7.0.0/normalize.css -->
    
      <style>
        .box {
          width:100% ;
          height:80px;
          background-color: red;
        }
    
        /* 屏幕小于 375 px 则是下面的样式 */
        @media screen and (max-device-width : 375px){
          .div1 {
            width:25%;
            background-color: green;
            height:80px;
          }
        }
    
        /* 屏幕大于 376 小于 414 px 则使用下面的样式 */
        @media screen and (min-device-width : 376px) and (max-device-width:414px){
          .div1 {
            width:50%;
            background-color: blue;
            height:80px;
          }
        }
    
        /* 小于等于 375px 使用以下样式  */
        @media screen and (max-device-width: 375px) {
          .menuitem1 {
            height: 100px;
            width: 100%;
            background-color: yellow;
          }
          .menuitem2 {
            height: 100px;
            width: 100%;
            background-color: blue;
          }
          .menuitem3 {
            height: 100px;
            width: 100%;
            background-color: #cceedd;
          }
    
          .menuitem4 {
            height: 100px;
            width: 100%;
            background-color: black;
          }
        }
    
        /* 大于等于 376px 使用以下样式 */
        @media screen and (min-device-width: 376px) {
          .menu {
            display: flex;
          }
          .menuitem1 {
            height: 100px;
            width: 100%;
            background-color: yellow;
          }
          .menuitem2 {
            height: 100px;
            width: 100%;
            background-color: blue;
          }
          .menuitem3 {
            height: 100px;
            width: 100%;
            background-color: #cceedd;
          }
          .menuitem4 {
            height: 100px;
            width: 100%;
            background-color: black;
          }
        }
      </style>
    </head>
    <body>
    
      <div id="contnainer" class="box">
        <div class="div1"></div>
      </div>
      <!-- mediaquery 实现响应式布局 -->
      <div class="menu">
        <div class="menuitem1"></div>
        <div class="menuitem2"></div>
        <div class="menuitem3"></div>
        <div class="menuitem4"></div>
      </div>
    
    </body>
    </html>
    

    以上代码就实现了上述效果图,代码注释清楚,这里也不多说了

    二、rem「font size of the root element」

    1、什么是 rem

    rem 就是根据网页根元素「html」来设置字体大小,这有什么用呢?这是移动 webapp 的最佳的适配方案「目前来说」,既然说是最佳的适配方案,那肯定还有别的适配方案,先看看都有那些适配方案吧

    • 1、viewport缩放「被废弃了」
    • 2、宽度固定两边留白「体验很差」
    • 3、响应式布局「工作量太大,针对不同的分辨率写一套 android 下估计开发者就疯了」

    2、如何适配

    我们先来看一个简单的例子吧,然后就能得到一些启发和感悟

    • 1、新建一个 rem.html 然后输入以下内容
    <!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">
      <!-- 重置默认的 css 样式 ,类似于 reset.css -->
      <link rel="stylesheet" href="../css/normalize.css">
      <title>rem demo</title>
    
      <style>
        .box {
          width: 100px;
          height: 100px;
          background-color: red;
          text-align: center;
        }
        .test {
          font-size: 16px;
          line-height: 100px;
        }
      </style>
    </head>
    <body>
      
      <div class='box'>
        <span class="test">测试</span>
      </div>
    
    </body>
    </html>
    
    

    很简单就是一个宽高为 100px 的 div 并且里面有一个居中的文字大小为 16px

    • 2、运行查看结果
    px 显示效果

    从图中我们可以看到,不管我们是什么分辨率的机型下,div 宽高都为 100px,这是不合理的,根本就没有适配「就是写死的呀」

    • 3、由于 2 中的效果是写死的,我们来看看 rem 是如何适配的,稍微把代码改一下

    我们知道 rem 和 html 下的 font-size 有关,我们来改代码吧

    <!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">
      <!-- 重置默认的 css 样式 ,类似于 reset.css -->
      <link rel="stylesheet" href="../css/normalize.css">
      <title>rem demo</title>
    
      <style>
         html {
           font-size: 16px;
         }
        .box {
          width: 10rem;
          height: 10rem;
          background-color: red;
          text-align: center;
        }
        .test {
          font-size: 1rem;
          line-height: 10rem;
        }
      </style>
    </head>
    <body>
      <div class='box'>
        <span class="test">测试</span>
      </div>
    </body>
    </html>
    
    

    ps: 这里说明几点

    为什么这里 font-size 要写成 16px ,因为大部分浏览的默认字体都是显示 16px,我们从 chrome 调试工具中可以看到

    chrome 默认的 font-size

    html 默认的 font-size 大小就 = 1rem , 从上面代码我们可以看到 box 的宽高都为 10rem 即 160px ,我们来验证一下,运行看结果

    没有改变 rem

    果然是 160px「肯定在别的分辨率上也是 160px」,这有个毛用呀,不就是把 100px 转化成 160px 了吗?还不是没有适配呀「大家是不是有这个疑问」,别急马上揭晓答案

    我们可以想一下,rem 和 font-size 有关,那么如果我们能动态的修改 font-size 的大小,那么以 rem 为单位的宽高等不就自动适配了吗。我们来一下修改 font-size 的效果

    修改 font-size

    看到了吧,我们手动修改 font-size 的值 div 的宽高就会动态改变「如果在不同分辨率的手机上设置不同和 font-size 那不就达到适配的效果了」

    三、适配手段

    我们知道只要动态的修改 font-size 使用 rem 就可以适配多种手机了

    • 1、通过 media query 来设置 font-size,比如:
    html {
        font-size : 20px;
    }
    @media only screen and (min-width: 401px){
        html {
            font-size: 25px !important;
        }
    }
    @media only screen and (min-width: 450px){
        html {
            font-size: 26.75px !important;
        }
    }
    @media only screen and (min-width: 481px){
        html {
            font-size: 30px !important; 
        }
    }
    
    • 2、通过 js 来设置

    估计上面的方法能把人写疯,特别对于 android 这个多样机型来说「一般只适配常用的分辨率」,那就有了下面的方法,使用 js 来动态设置 font-size

    再说 js 动态修改 font-size 之前,先推导下 px 转化成 rem 的公式:

    比如:1rem = 16px「rem 的基准值」 ; 48px = 48/16 = 3rem,

    所以得出:

    rem = 需要转化的px/rem基准值
    

    rem 基准值「和 html 的 font-size 有关」如何算,这里给出一个比较常见的做法,就是用设计稿的屏幕宽度/10 ,原则上除以多少都可以,除以 10 是为了好除「业界基本上也是这样做的」,比如以 iPhone 6p「414*736」 为例子,那么 rem 的基准值就是 414/10 = 41.4px,然后我们就是要不停的改变这个页面基准值的值即可,我们只要记住一点,rem 的基准值是根据设计稿来决定的

    我们也知道了,如果把一个 px 转化成 rem 那么就是使用 px/rem基准值,这样界面中的 css 中有太多的 px ,如果一个个除下来人头发都白了「也不一定能除完,当然网上也有在线转换网站,就是这样也累呀」,我们可以使用 sass「css 扩展语言」 来解决这个问题

    1、sass 的安装

    gem install sass
    gem install compass
    

    以上安装速度如果慢的话,可以切换成淘宝的 gem「安装基于ruby的软件」源

    • 3、查看是否安装成功
    sass-v

    如果看到这个,就证明 sass 安装成功了

    2、写个 demo 感受一下

    • 1、新建一个 usesass.html
    <!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">
      <link rel="stylesheet" href="../css/normalize.css">
      <link rel="stylesheet" href="../css/usesass.css">
      <title>使用 sass </title>
    </head>
    <body>
    
      <div class="box">
        <div class="item"><span>1</span></div>
      </div>
    
    </body>
    </html>
    

    细心的朋友会发现,我们这里引入了一个 usesass.css 样式文件,哪来的?目前这个文件是不存在的,完后我们使用 sass 直接转换成普通的 css 文件即可

    • 2、在 css 目录下新建 usesass.scss 文件

    scss 和 sass 文件区别,前者对格式没有严格要求,后者对格式有严格的要求「没有大括号等,这里我们使用 scss」

    .box{
      background-color: red;
      width: 100px;
      height: 100px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .item {
      background-color: yellow;
      width:50px;
      height:50px;
    }
    
    • 3、scss 肯定是直接不能使用的,我们要转化一下,使用 sass 命令

    我们进入到 css 目录下使用如下命令

    sass usesass.scss usesass.css
    

    这样就会在 css 目录下创建一个 usesass.css 文件并且把 sass 转化成 css 了,我们看看这个 css 文件

    .box {
      background-color: red;
      width: 100px;
      height: 100px;
      display: flex;
      justify-content: center;
      align-items: center; }
    
    .item {
      background-color: yellow;
      width: 50px;
      height: 50px; }
    

    看起来和上面的 sass 文件是一毛一样的「原因是我们没有使用 sass 的扩展语法,sass 是兼容所有的版本的 css 的」

    • 4、运行一下看结果
    sass 转 css

    没有什么毛病,sass 成功转化成 css 并且显示出结果了

    3、使用 sass 来转化 px--rem ,并且使用 js 动态设置 font-size

    • 1、提供 px2rem() 函数

    在 sass 中我们可以使用函数,我们定义一个函数用来转化 px 到 rem,这里以视觉稿为 iphone 6p「414*736」 为例子,那么 rem 的基准值就是 41.4px ,我们在 usesass.sass 中添加如下代码,并且修改 box 的宽高 px 为 rem「调用 px2rem()方法」

    @function px2rem($px){
      // rem基准值
        $rem : 41.4px;
        @return ($px/$rem) + rem;
    }
    
    .box{
      background-color: red;
      width: px2rem(100px);
      height: px2rem(100px);
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .item {
      background-color: yellow;
      width:px2rem(50px);
      height:px2rem(50px);
    }
    
    • 2、使用 js 动态的修改 font-size 的值

    在 usesass.html 添加以下动态修改 font-size 的代码

    <script>
      // 取得屏幕宽度
      var devicewidth = document.documentElement.clientWidth || document.body.clientWidth
      //动态设置 html font-size 值
      document.getElementsByTagName('html')[0].style.fontSize = devicewidth / 10 + 'px';
    </script>
    
    • 3、记得一定要把 sass 转化成 css
    sass usesass.scss usesass.css
    

    我们再看看 usesass.css 文件

    .box {
      background-color: red;
      width: 2.4154589372rem;
      height: 2.4154589372rem;
      display: flex;
      justify-content: center;
      align-items: center; }
    
    .item {
      background-color: yellow;
      width: 1.2077294686rem;
      height: 1.2077294686rem; }
    

    我们看 px 成功的转化成 rem 了,这样我们就可以动态的修改 rem 了

    • 4、看看效果吧

    先看效果之前,我们为了方便测试,来给动态修改 rem 添加一个事件吧,否则每次修改分辨率都要重新刷新一下浏览器「这里是为了演示添加的代码」

    // 窗口大小改变时的回调
    window.onresize = function(){
      // 取得屏幕宽度
      var devicewidth = document.documentElement.clientWidth || document.body.clientWidth
      //动态设置 html font-size 值
      document.getElementsByTagName('html')[0].style.fontSize = devicewidth / 10 + 'px';
    }
    
    使用 js 动态修改 font-size

    依据前面我们知道,我们是以设计稿为 iphone 6p 基准来设置的「在此手机上宽高就是 100 px」,从上图可以看到确实在不同的分辨率手机下 box 的宽高等比缩放,这就达到了适配的目的,基本上 rem 适配手机 webapp 方法就说完了

    四、参考资料

    腾讯全端AlloyTeam团队--移动web适配利器--rem:http://www.alloyteam.com/2016/03/mobile-web-adaptation-tool-rem/


    点赞富一生,转发富五代,更多文章请关注我的微信公号来查阅

    公众号:TigerChain

    相关文章

      网友评论

        本文标题:06、手把手教Vue--移动webapp适配方案--rem

        本文链接:https://www.haomeiwen.com/subject/yfswnftx.html