页面移动端适配方案再总结

之前在看 CSS 深入浅出的课程就写下了这篇笔记。在工作后,经历了真实的项目,再结合实际的项目来补充之前的笔记。

使用「媒体查询」方案

媒体查询语法

// 多个条件时用 and 
@media (min-width:400px) and (max-width: 800px){
  // ... 匹配的样式
}
<link rel='stylesheet' href='/path/style.css' media="(条件样式)">

注意:多个媒体查询同时生效的优先级的情况

「媒体查询方案」的麻烦之处

用媒体查询,虽然,可以做到 PC 和移动端的响应式页面。但是,在实际使用时代码会比较凌乱。 大多数功能复杂的网站,在需要做 PC 和移动端的响应式时,会选择通过后端来处理的方式。也就是做两套 HTML 页面。通过 HTTP 请求头部的 UserAgent 来判断用户是使用哪个客户端,来决定返回给客户端哪一套 HTML。如淘宝(taobao.com) 在用移动端浏览器访问时会将页面重定向到手机淘宝(m.taobao.com

在移动端需要加一个 <meta> 标签

<meta name='viewport' content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"></meta>

分析移动端交互与 PC 端的差异

  • 移动端没有 hover 状态
  • 移动端没有 resize
  • 移动端没有滚动条
  • 移动端有 touch 事件

使用「动态REM」方案

常用 CSS 长度单位

  • px 绝对长度单位,屏幕中的一个像素
  • em 相对长度单位,这个单位表示元素的 font-size 的计算值。如果用在 font-size 属性本身,它会继承父元素的 font-size。
  • rem 这个单位代表根元素的 font-size 大小(例如 元素的 font-size)
  • vh 视口高度的 1/100。
  • vw 视口宽度的 1/100。

MDN 对 rem 的描述

该单位在实际使用中一般用于创建完美的可扩展布局。如果不被目标浏览器支持,可以使用em单位,虽然会稍微复杂一些。

「媒体查询」方案分析,进行改进

在进行移动端适配时,开始想到的是用媒体查询来实现。但细想一下,各种手机屏幕宽度参差不齐,会需要写很多套 CSS。

另外一个方案,用百分比布局。各元素的宽高、内外边距都使用百分比为单位。这种方案的局限是高度和宽度无法关联(百分比是相对父元素的宽度或高度)。在需要宽度和高度固定比例时无法实现

创建完美的可扩展布局的思路

核心思想: 一切单位以屏幕宽度为准

但上面列举的单位中,和屏幕宽度有联系的单位vw ,它目前兼容性比较差。其他的各种单位又不能和屏幕宽度关联。聪明的前端师傅们想出了一个好办法,就是通过 JavaScript 来间接的关联rem 和屏幕宽度,具体步骤如下:

  1. 页面加载时,通过 JavaScript 来获取当前屏幕的宽度
  2. 再用 JavaScript 来写 CSS 样式(添加一段CSS代码字符串到页面),从而改变 <html>font-size 的值。也就动态的改变了 rem
  3. 我们写页面元素的宽高的值,就全都以 rem (屏幕宽度)为准

实现动态 REM 的核心代码

function setRem () {
  const width = document.documentElement.clientWidth
  const fontSize = width / 10 + 'px'
  document.documentElement.style.fontSize = fontSize
}

window.addEventListener('resize', setRem, false)

setRem()

再进一步,工程化使用

  • 在写代码时,需要把设计稿中的每像素的值,手动计算出所对应的 rem的值是多少。这样的做法效率较低,我们可以通过工具 scssless 等工具来帮助我们,在 scss中定义好一个换算的函数,在写代码时就不需要去手动计算了。

看看项目中的实际使用

为什么是 const rem = Math.round(width / 18.75)

这里的 18.75是怎么来的呢?我们计算页面的宽度 rem 值的时候,是使用某一款移动设备的分辨率来计算的,设计稿用的是 iPhone 6 的分辨率 375 * 667,它的宽度为 375 px,20px 为 1rem,那么 375px 就是 18.75 rem

vw 单位来实现

参考链接