vue.jsVue.jsVue移动端

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

2018-09-19  本文已影响330人  TigerChain

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

大纲

教程简介

正文

一、media query「媒体查询」

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

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

1、media query 的作用

2、media query 的语法

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

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

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

描述
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 的最佳的适配方案「目前来说」,既然说是最佳的适配方案,那肯定还有别的适配方案,先看看都有那些适配方案吧

2、如何适配

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

<!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

px 显示效果

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

我们知道 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 就可以适配多种手机了

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; 
    }
}

估计上面的方法能把人写疯,特别对于 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的软件」源

sass-v

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

2、写个 demo 感受一下

<!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 文件即可

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;
}

我们进入到 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 的」

sass 转 css

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

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

在 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);
}

在 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>
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 了

先看效果之前,我们为了方便测试,来给动态修改 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

上一篇 下一篇

猜你喜欢

热点阅读