Skip to content

移动端适配与 rem(二) ​

本页对应 移动端适配与 rem,共 7 段视频,约 1 小时 2 分。

学习目标 ​

  • 能用自己的话解释移动端适配的含义,并区分百分比布局“宽度适配、高度固定”与 rem 等比适配的差异及适用场景。
  • 能使用百分比布局完成底部固定导航栏案例,包括固定定位、宽度 100%、子项 25% 分配、图片尺寸与居中处理,并在不同视口下验证宽度自适应、高度固定。
  • 能说明 rem 是相对于 html 根字号的相对单位,完成 rem 与 px 的换算,并解释“只使用 rem 不会自动适配”的原因。
  • 能正确书写媒体查询语法,检测视口宽度,并依据 320px、375px、414px 等宽度为 html 设置不同根字号,验证 rem 元素尺寸随设备变化。
  • 能识别浏览器缩放导致媒体查询宽度出现小数或设备宽度不准确的问题,并说明将缩放调为 100% 或按实际视口宽度调整的处理方式。
  • 能引入 flexible.js,使用 rem 编写元素,并在多种设备及缩放条件下验证自适应效果,说明其相比手写媒体查询的优势。

知识点 ​

从百分比布局的局限说起 ​

为什么需要 rem:转写稿里先讲了百分比布局:宽度用百分比,高度固定,所以同一个页面在不同设备上“宽会变、高不变”。这能适配一部分场景,但做不到宽高等比缩放。
怎么想:如果希望同一个盒子在 iPhone 5、iPhone 6/7/8、iPhone 6/7/8 Plus 等不同视口下按比例变化,就不能只靠固定 px,也不能只靠百分比宽。需要找一个“会跟着设备视口变化的单位”。
怎么做:先理解 rem 是相对单位,再配合媒体查询或 flexible.js 改变 HTML 根字号。
易错点:不要误以为写了 5rem 就自动适配;如果所有设备下 HTML 根字号都不变,5rem 的结果也不会变。

rem 是什么:相对 HTML 根字号 ​

为什么需要:px 是固定像素单位,换设备后同一个 80px 盒子还是 80px,不会等比变化。
怎么想:rem 类似 px,也是单位,但它是相对单位。笔记明确:1rem = 1HTML字号大小,也就是相对于 HTML 标签的字号计算结果。
怎么做:给 HTML 设置字号后,元素用 rem 写尺寸。例如根字号为 16px 时,5rem = 5 × 16px;根字号为 14px 时,5rem = 5 × 14px。
易错点:单独使用 rem 不会产生适配效果。转写稿调试时发现,多个设备下盒子都是 80×48,原因是各设备根字号默认都为 16px,根字号没变,rem 计算结果自然不变。

媒体查询:先识别视口宽度 ​

为什么需要:要让 rem 适配生效,必须根据设备视口宽度设置不同的 HTML 根字号;第一步就是知道当前设备视口有多宽。
怎么想:媒体查询能检测视口宽度,当某个条件成立时,执行对应 CSS 样式。
怎么做:按笔记格式写 @media,小括号里写条件,大括号里写差异化样式。注意媒体查询条件后不要像普通属性那样随手加分号。

媒体查询示意图

css
@media (width:320px) {
  html {
    background-color: green;
  }
}

易错点:媒体查询不是“给元素直接写样式”,而是“条件成立才执行”。调试时如果设备宽度因缩放显示成 375.2px,而条件写 375px,就可能匹配不上;转写稿建议先把缩放调回 100%,或按实际视口宽度处理。

rem 布局:把网页等分成 10 份 ​

为什么需要:只有 rem 和媒体查询还不够,还要约定“根字号到底设多大”。
怎么想:目前 rem 布局方案中,将网页等分成 10 份,HTML 标签的字号为视口宽度的 1/10。这样不同视口下根字号不同,rem 尺寸就跟着变。
怎么做:例如视口 320px,根字号为 32px;视口 375px,根字号为 37.5px;视口 414px,根字号为 41.4px。
易错点:除以 10 是习惯约定,不是唯一数学规则;但一旦项目采用某个比例,就要统一。不要这个设备除以 10、那个设备除以 20。

rem布局等分示意图

flexible.js:自动设置根字号 ​

为什么需要:手写媒体查询要枚举大量设备,设备一多就很麻烦;缩放还可能让视口值出现小数。
怎么想:flexible.js 是手淘开发的移动端适配 js 库,核心原理是根据不同视口宽度给 HTML 根节点设置不同 font-size。
怎么做:在页面底部引入脚本:

html
<body>
  ......
  <script src="./js/flexible.js"></script>
</body>

易错点:它解决的是“自动设置根字号”,不是让所有 CSS 都自动变成 rem;页面里的尺寸仍要按 rem 规则书写。转写稿还提醒:引入后不必自己枚举 320、375、414 等设备,缩放场景下也能继续适配。

rem 移动适配的计算流程 ​

为什么需要:写页面时设计稿给的是 px,需要换算成 rem。
怎么想:先确定基准根字号,再算元素 rem 值。
怎么做:

  1. 确定基准根字号:查看设计稿宽度 → 确定参考设备宽度(视口宽度)→ 确定基准根字号(1/10 视口宽度)。
  2. 计算 rem 尺寸:rem单位的尺寸 = px单位数值 / 基准根字号。
    易错点:基准根字号要和当前适配方案一致;不要把设计稿 px 直接抄成 rem,也不要在根字号未随视口变化时误判“已经适配”。

先理解 Less 的定位 ​

Less 是一个 CSS 预处理器,Less 文件后缀是 .less。它扩充了 CSS 语言,使 CSS 具备一定的逻辑性、计算能力。为什么需要它?因为原生 CSS 在变量、嵌套、公共样式复用等方面不够方便,页面一大就难维护。怎么想?把 Less 当成“更会计算的 CSS 写法”,先写 Less,再让它生成浏览器能识别的 CSS。怎么做?在 VS Code 中安装 Easy LESS 插件,保存 .less 文件后自动生成对应的 .css 文件。易错点:浏览器不识别 Less 代码,目前阶段网页要引入对应的 CSS 文件,不能直接引入 .less 文件。

Easy LESS 保存后生成 CSS 文件

注释:让代码可读,也方便临时屏蔽 ​

为什么需要注释?样式多了以后,需要说明某段代码的用途,调试时也常要临时屏蔽代码。怎么想?Less 支持两种注释:单行注释和块注释。怎么做?单行注释语法是 // 注释内容,快捷键是 Ctrl + /;块注释语法是 /* 注释内容 */,快捷键是 Shift + Alt + A。易错点:单行注释是 Less 中常见的注释写法,但最终生成 CSS 时要关注注释是否保留;块注释更接近传统 CSS 注释。写注释时不要用错符号,否则可能把后续样式一起注释掉。

运算:让尺寸计算写进样式里 ​

为什么需要运算?做布局时常要算宽度、间距、比例,如果手算后再写死,修改起来麻烦。怎么想?Less 允许在样式里直接写计算表达式,让代码表达“怎么算”,而不是只写“算完是多少”。怎么做?加、减、乘可以直接书写计算表达式;除法需要添加小括号或点号写法;表达式存在多个单位时,以第一个单位为准。易错点:除法不要按普通 CSS 习惯直接写,否则可能不按预期计算;单位不统一时不要凭感觉,记住“多个单位以第一个单位为准”;运算结果要保存生成 CSS 后到浏览器里验证。

Less 运算示例

嵌套:快速生成后代选择器 ​

为什么需要嵌套?原生 CSS 写后代选择器时,父级选择器要反复写,层级一深就冗长。怎么想?把子级样式写在父级选择器的大括号里,让结构像 HTML 的层级一样清晰。怎么做?在父选择器内部继续写子选择器,Less 会生成对应的后代选择器。易错点:嵌套不是越深越好,层级过深会让生成的 CSS 选择器很长,后续覆盖样式更麻烦;要分清“后代”关系,不要把所有选择器都无脑塞进父级。

Less 嵌套生成后代选择器

提示:用 & 表示当前选择器,不会生成后代选择器,通常配合伪类或伪元素使用。为什么需要 &?因为写 :hover、::before 这类伪类或伪元素时,如果直接嵌套,可能被编译成后代选择器,语义就变了。怎么做?在需要紧贴当前选择器的位置写 &。易错点:该加 & 的地方漏加,会导致选择器关系错误;不需要当前选择器时也不要乱加。

使用 & 表示当前选择器

变量:把常用数据存起来 ​

为什么需要变量?颜色、尺寸等值在多个地方重复出现,修改时容易漏改。怎么想?变量就是一个容器,用来存储数据,方便使用和修改。怎么做?定义变量:@变量名: 数据;;使用变量:CSS属性:@变量名;。例如:

less
// 定义变量
@myColor: pink;
// 使用变量
.box {
  color: @myColor;
}
a {
  color: @myColor;
}

易错点:变量名要以 @ 开头;定义时用冒号,使用时分号不要漏;变量名要有意义,不要用 @a1、@a2 这类看不出用途的名字。修改主题色时只改变量定义处,但保存后要确认生成的 CSS 是否同步更新。

导入:复用公共 Less 样式 ​

为什么需要导入?多个页面常共用基础样式,如果每个文件都复制一遍,维护成本高。怎么想?把公共样式放在单独文件里,在需要的地方导入。怎么做?语法是 @import “文件路径”;。提示:如果是 less 文件可以省略后缀。例如:

less
@import './base.less';
@import './common';

易错点:路径要写对,注意当前文件和目标文件的相对位置;能省略后缀的是 Less 文件,不要把这个规则乱套到其他资源上;导入后保存,检查生成的 CSS 是否包含公共样式。

导出:控制生成 CSS 的位置 ​

为什么需要导出设置?Easy LESS 默认会生成 CSS,但实际项目常希望统一放到某个目录,避免文件散落。怎么想?在 Less 文件里用注释语法告诉插件把生成的 CSS 存到哪里。怎么做?在 less 文件的第一行添加 // out: 存储URL。提示:文件夹名称后面添加 /。例如:

less
// out: ./index.css
// out: ./css/

易错点:导出注释要放在第一行附近,位置不对可能不生效;写文件夹时末尾加 /,写具体文件时写完整文件名;修改导出路径后要重新保存并检查目标位置是否生成 CSS。

禁止导出:有些 Less 只做公共片段 ​

为什么需要禁止导出?有些 Less 文件只是变量、混入或公共片段,不需要单独生成 CSS。怎么想?通过第一行注释关闭该文件的自动导出。怎么做?在 less 文件第一行添加:// out: false。易错点:禁止导出后,如果这个文件本身被 HTML 直接需要,就会缺少 CSS;公共文件被导入时仍要确认导入路径和编译结果。

禁止导出写法示例

调试与验证:按“保存—生成—引入—刷新”检查 ​

写完 Less 后,先保存文件,看 Easy LESS 是否生成对应 CSS;再确认 HTML 引入的是生成的 CSS 文件,而不是 .less 文件;最后刷新浏览器查看效果。若样式没变化,按顺序排查:插件是否启用、导出路径是否正确、HTML 路径是否指向生成后的 CSS、浏览器是否缓存。这样能把“Less 写法问题”和“引入路径问题”分开定位。

课件图示 ​

课件第28页:l Less是一个CSS预处理器, Less文件后缀是.less。扩充了 CSS

课件第30页:less – 运算 运算: l 加、减、乘直接书写计算表达式 l 除法需要添加

课件第31页:less – 嵌套 作用:快速生成后代选择器 提示:用 & 表示当前选择器,不会

课件第21页:思考 l 设备宽度不同,HTML标签字号设置多少合适? p 设备宽度大,元素尺寸

课件第22页:目前rem布局方案中,将网页等分成10份, HTML标签的字号为视口宽度的 1/

课件第24页:思考: l 工作中,书写代码的尺寸要参照设计稿尺寸,设计稿中是px还是rem?

课件第25页:l 目标: 计算68px是多少个rem?(设计稿适配375px视口) l N *

代码示例 ​

示例 1:rem + 媒体查询实现移动适配(HTML/CSS)

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>rem + 媒体查询适配</title>
  <style>
    /* 1. 媒体查询:检测视口宽度,给 html 设置不同根字号
       根字号 = 视口宽度 / 10(网页等分成 10 份,1 份就是 1rem) */
    @media (width: 320px) {
      html { font-size: 32px; }
    }
    @media (width: 375px) {
      html { font-size: 37.5px; }
    }
    @media (width: 414px) {
      html { font-size: 41.4px; }
    }

    /* 2. 元素尺寸用 rem 写:rem 值 = px 值 / 基准根字号
       设计稿 375 宽下量到 187.5px → 187.5 / 37.5 = 5rem */
    .box {
      width: 5rem;
      height: 3rem;
      background-color: pink;
      font-size: 0.4rem;
    }
  </style>
</head>
<body>
  <div class="box">rem 适配的盒子</div>
</body>
</html>

要点解释:

  • 1rem = 1 个 html 标签的字号,rem 是相对单位,相对的是 HTML 根字号。
  • 媒体查询小括号里写 width: 320px,后面不能加分号(和普通 CSS 属性写法不同),格式错整段样式都不生效。
  • 关键行 html { font-size: 37.5px; }:375 设备下 1rem 就是 37.5px,元素随设备自动等比缩放。
  • 易错点:只写 rem 单位不设根字号不会适配——各设备 html 默认字号都是 16px,盒子永远一样大。
  • 易错点:浏览器缩放不是 100% 时,视口宽会变成 375.2 之类的值,媒体查询匹配不上,先把缩放调回 100%。
  • 易错点:除以几要统一——全除以 10 就都除以 10,不能这个除以 10、那个除以 20。

示例 2:引入 flexible.js 做 rem 适配(HTML/JS)

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>flexible.js 适配</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    .box {
      width: 5rem;   /* 375 设备:5 × 37.5 = 187.5px;414 设备:5 × 41.4 = 207px */
      height: 3rem;
      background-color: skyblue;
    }
  </style>
</head>
<body>
  <div class="box"></div>

  <!-- 实际项目写法:<script src="./js/flexible.js"></script> -->
  <!-- 下面等价演示 flexible.js 的核心原理:视口宽度 / 10 设置 html 字号 -->
  <script>
    (function () {
      function setRem() {
        var html = document.documentElement;       // html 根节点
        var width = html.clientWidth;              // 当前视口宽度
        html.style.fontSize = width / 10 + 'px';   // 根字号 = 视口宽 / 10
      }
      setRem();
      window.addEventListener('resize', setRem);   // 视口变化时重新计算
    })();
  </script>
</body>
</html>

要点解释:

  • flexible.js 是手淘开发的移动端适配 JS 库,核心原理就是“根据不同的视口宽度给 html 根节点设置不同的 font-size”。
  • 引入位置按笔记写在 <body> 内、页面结构之后:<script src="./js/flexible.js"></script>。
  • 关键行 html.style.fontSize = width / 10 + 'px':和手写媒体查询的算法一致,只是它覆盖所有设备,不用一条条写媒体查询。
  • 易错点:rem 换算的基准必须和 JS 的除法一致(都按 10 份),否则尺寸整体偏大或偏小。
  • 易错点:JS 里的 document.documentElement 是 html 元素,不是 body,写错根字号不生效。

示例 3:Less 变量、运算、嵌套、导入与导出(.less)

less
// out: ./css/

// 导入公共样式文件(less 文件可省略后缀)
@import './base.less';
@import './common';

// 变量:存储数据,方便使用和修改
@myColor: pink;
@baseFont: 37.5;

.box {
  // 加、减、乘直接书写计算表达式
  width: 200px + 100px;      // 300px
  height: 100px * 2;         // 200px

  // 除法必须加小括号(或 ./),表达式有多个单位以第一个单位为准
  margin-left: (100px / 2);  // 50px

  // 用变量:rem 值 = px 值 / 基准根字号
  padding: (375 / @baseFont) * 1rem;   // 10rem

  color: @myColor;

  // 嵌套:快速生成后代选择器
  .son {
    width: 5rem;

    // & 表示当前选择器,不生成后代选择器,通常配合伪类/伪元素
    &:hover {
      color: red;
    }
  }
}

a {
  color: @myColor;
}

要点解释:

  • 第一行 // out: ./css/ 是导出路径,保存 less 后 Easy LESS 插件自动生成 CSS;写 // out: false 则禁止导出。
  • @myColor: pink; 定义变量,color: @myColor; 使用变量,改一处即可全局生效。
  • 运算关键点:加减乘直接写,除法必须用小括号包起来;表达式存在多个单位时以第一个单位为准。
  • &:hover 编译成 .box .son:hover 中的 .son:hover(& 代表当前选择器本身),不加 & 会变成后代选择器 .box .son :hover。
  • 易错点:浏览器不识别 Less 代码,网页里必须引入编译后生成的 .css 文件。
  • 易错点:单行注释 // 不会编译进 CSS,块注释 /* */ 会保留在生成的 CSS 里。

常见错误 ​

  1. 现象:元素写了 rem,但换设备后大小不变 → 原因:根字号未随视口变化,仍是默认值 → 修法:用媒体查询按视口改 html 字号,或引入 flexible.js。
  2. 现象:媒体查询代码不生效 → 原因:括号内条件后误加 ;,或选择器/大括号格式写错 → 修法:改为 @media (width:375px){ ... },条件后不加分号。
  3. 现象:Less 中除法编译结果不对 → 原因:除法未加小括号或未用 ./ → 修法:写成 (100px / 2) 或 100px ./ 2。
  4. 现象:HTML 引入 .less 后页面无样式 → 原因:浏览器不识别 Less,需先编译为 CSS → 修法:用 Easy LESS 生成 CSS,页面引入生成的 .css。
  5. 现象:保存 Less 后没有生成 CSS → 原因:Easy LESS 未启用、导出注释不在首行或路径写错 → 修法:首行写 // out: ./css/,检查插件和保存状态。
  6. 现象:375 设备下媒体查询匹配不准 → 原因:浏览器缩放导致视口变成 375.2 等小数 → 修法:调试时缩放调回 100%,或按实际视口值临时调整。
  7. 现象:引入 flexible.js 后仍不适配 → 原因:script 路径错误或未放在页面底部 → 修法:检查相对路径,放在 </body> 前引入。
  8. 现象:嵌套中写 :hover 生成了后代选择器 → 原因:伪类前未加 & → 修法:写成 &:hover。

练习 ​

  1. 设计稿宽 375px,基准根字号为 37.5px。把元素宽 150px、高 80px 转成 rem。
  2. 找出并改正:@media (width:320px;) { html { font-size: 32px; } }
  3. 将 .box 内 .item 的 :hover 用 Less 嵌套改写,要求不生成后代选择器。
  4. 按步骤检查一个 rem 页面:根字号是否变化、flexible.js 是否引入成功、页面缩放是否为 100%。
  5. 某百分比布局在 iPhone 5 上宽度合适但高度不缩放,说明应改用什么方案,并写出改造要点。

原视频对照 ​

#视频时长
1适配方案02:45
2百分比布局12:18
3rem体验03:50
4rem介绍12:58
5媒体查询08:07
6rem适配13:49
7flexible使用08:38

小结 ​

  1. rem 适配成立的前提是根字号随视口变化,单写 rem 不等于适配。
  2. 媒体查询适合理解原理和小范围演示,真实移动端适配优先用 flexible.js。
  3. 基准根字号通常按设计稿宽度除以 10 确定,换算公式必须统一。
  4. Less 必须编译成 CSS 才能被浏览器使用,导出注释放首行更稳。
  5. Less 除法优先加小括号,避免编译结果与预期不一致。
  6. 嵌套配合 & 处理伪类/伪元素,能避免误生成后代选择器。
  7. 调试适配问题先查根字号、编译产物、引入路径和浏览器缩放。
  8. 百分比布局主要解决宽度适配,宽高等比缩放应转向 rem 或 vw/vh 方案。