Skip to content

大屏与移动端自适应布局核心笔记

本文档旨在整理和归纳前端开发中,实现大屏及移动端项目屏幕自适应的核心思想、主流方案和注意事项。

一、核心基本原则

无论采用何种方案,自适应布局都围绕以下两个基本原则:

  1. 布局技术:优先采用 Flex 弹性布局 (display: flex) 来处理元素的排列、对齐和间距,它能灵活地适应空间变化。
  2. 尺寸单位:放弃固定单位 px,改用相对尺寸单位,主要有 remvwvh

二、两种主要的自适应场景

场景1:不同屏幕尺寸,布局结构完全不同

当 PC 端和移动端的界面设计差异巨大,无法通过简单的尺寸缩放来适配时(例如,PC 端是多栏布局,移动端是单栏信息流),通常采用以下两种策略:

  • 站点切换:通过 JavaScript 检测屏幕宽度(如 window.innerWidth),当宽度小于某个阈值(如 960px)时,自动跳转到移动版站点(例如从 www.domain.com 跳转到 m.domain.com)。
  • 媒体查询 (Media Queries):使用 CSS 的 @media 规则,为不同的屏幕宽度范围编写两套独立的 CSS 样式。当屏幕尺寸变化时,浏览器会自动应用匹配的样式。
css
/* PC端样式 */
.container {
  width: 1200px;
  margin: 0 auto;
}

/* 当屏幕宽度小于等于 960px 时,应用以下移动端样式 */
@media (max-width: 960px) {
  .container {
    width: 100%;
  }
}

场景2:不同屏幕尺寸,布局结构保持一致(本篇重点)

当不同尺寸的屏幕只是UI元素的等比缩放,布局结构不变时,我们可以使用 remvw 来实现高保真的自适应效果。

三、REM 布局方案

rem 方案是目前应用最广泛、最灵活的方案之一。

1. 原理

rem (root em) 是一个相对单位,1rem 的大小等于 HTML 根元素的字体大小 (font-size)。

核心思想:通过 JavaScript 动态计算并修改 <html> 元素的 font-size,使得 1rem 的值与屏幕宽度成正比。这样,所有使用 rem 作为单位的元素尺寸,都能随着屏幕宽度的变化而等比缩放。

注意rem 本身不会自动适应屏幕,必须配合 JavaScript 才能实现自适应效果。

2. 核心 JS 算法

这段 JS 代码通常放在 HTML 的 <head> 标签中,以确保在 CSS 解析前执行。

换算公式当前 rem 值 = (当前设备宽度 / 设计稿宽度) * 设计稿基准 font-size

代码实现

html
<script>
  function setRem() {
    // 1. 设计稿宽度,例如我们最常用的 750px
    const designWidth = 750;
    // 2. 设计稿下的 rem 基准值,可自定义,此处以 100px 为例
    const baseFontSize = 100;

    // 3. 获取当前设备的宽度(视口宽度)
    let clientWidth = document.documentElement.clientWidth;

    // 4. 对移动端项目在PC端打开的情况做最大宽度限制
    //    确保计算的 font-size 不会过大
    const maxWidth = 750;
    clientWidth = Math.min(clientWidth, maxWidth);

    // 5. 计算当前应设置的 font-size
    const newFontSize = (clientWidth / designWidth) * baseFontSize;

    // 6. 设置给 html 元素
    document.documentElement.style.fontSize = newFontSize + 'px';
  }

  // 初始调用
  setRem();

  // 监听窗口尺寸变化,以便在PC端拖动浏览器窗口时也能实时响应
  window.addEventListener('resize', setRem);
</script>

算法解读

  • 以上述代码为例,当设备宽度为 750px (设计稿宽度) 时,<html>font-size 被设置为 100px
  • 当设备宽度缩小一半变为 375px 时,<html>font-size 会被 JS 计算并设置为 50px
  • Math.min(clientWidth, maxWidth) 这行代码的作用是:当在大于 750px 的 PC 屏幕上浏览时,clientWidth 始终按 750px 计算,防止页面元素被无限放大。

3. CSS 单位换算

设置好 JS 后,在编写 CSS 时,需要将设计稿上的 px 值手动换算成 rem

换算公式rem 值 = 设计稿元素尺寸 (px) / 设计稿基准 font-size

示例

  • JS 中设置的基准 font-size100px
  • 设计稿上一个盒子的宽度是 150px
  • 那么在 CSS 中,该盒子的宽度应写为:width: 1.5rem; (150 / 100)。

4. 自动化方案:postcss-px2rem

手动计算 rem 非常繁琐。在工程化项目中,我们可以使用 PostCSS 插件 postcss-px2rem 自动完成 pxrem的转换。

  1. 安装npm install postcss-px2rem --save-dev
  2. 配置 (以 Vite 为例):在 vite.config.js 中配置。
    javascript
    // vite.config.js
    import { defineConfig } from 'vite';
    import px2rem from 'postcss-px2rem';
    
    export default defineConfig({
      css: {
        postcss: {
          plugins: [
            px2rem({
              // remUnit 对应我们 JS 代码中的 baseFontSize
              remUnit: 100 
            })
          ]
        }
      }
    });
  3. 使用:配置完成后,在 CSS 文件中可以直接写设计稿的 px 值,构建工具会自动将其转换为 rem

如何处理不想被转换的 px? 如果某些 px 值(如边框 border: 1px solid black;)不希望被转换,可以将该样式写成内联 style,PostCSS 插件只会处理 .css 文件,不会处理内联样式。

四、VW / VH 布局方案

vw (viewport width) 和 vh (viewport height) 是更现代的自适应方案。

1. 原理

vwvh 是直接与视口(Viewport)尺寸绑定的单位。

  • 1vw = 1% 的视口宽度。
  • 1vh = 1% 的视口高度。

核心优势vw 单位会自动根据屏幕宽度的变化而变化,无需任何 JavaScript 代码介入,更加简单纯粹。

2. CSS 单位换算

换算公式vw 值 = (设计稿元素尺寸 (px) / 设计稿宽度) * 100

示例

  • 设计稿宽度为 750px
  • 设计稿上一个盒子的宽度是 100px
  • 那么在 CSS 中,该盒子的宽度应写为:width: 13.333vw; ((100 / 750) * 100)。

3. vh 的主要用途

vh 很少用于设置元素的 widthheight,它的主要应用场景是实现全屏布局

  • height: 100vh;:让元素的高度等于屏幕(视口)的可用高度。
  • 相比 height: 100%; (需要其所有父元素的高度也都是 100%),100vh 无需关心父元素,使用更便捷。

4. 自动化方案:postcss-px-to-viewport

rem 类似,vw 的换算也可以通过 PostCSS 插件自动完成。

  1. 安装npm install postcss-px-to-viewport --save-dev
  2. 配置 (以 Vite 为例):
    javascript
    // vite.config.js
    import { defineConfig } from 'vite';
    import pxToViewport from 'postcss-px-to-viewport';
    
    export default defineConfig({
      css: {
        postcss: {
          plugins: [
            pxToViewport({
              // viewportWidth 对应设计稿的宽度
              viewportWidth: 750,
            })
          ]
        }
      }
    });

五、方案对比与总结

特性REM 方案VW 方案百分比 (%)
核心原理相对 <html>font-size相对视口的宽度相对父元素的尺寸
JS依赖必须,用来动态改变根 font-size不需要,单位本身就是响应式的不需要
灵活性。可通过JS设置最大/最小宽度限制,完美兼容PC端浏览。。直接与视口挂钩,在PC端浏览时可能导致元素过大,布局错乱。。适用于与父元素成比例的场景。
适用场景需要兼容PC端浏览的移动端项目;需要精细控制缩放比例的场景。纯移动端项目(如App内嵌页);追求开发简洁性的项目。元素尺寸需根据父容器而非视口来确定的场景。
简易性较复杂(需要JS脚本)非常简单简单,但易与 rem/vw 混淆

总结:

  • 首选 rem:如果你的移动端项目需要在PC端也能良好地被访问rem 是最佳选择,因为它的灵活性最高。
  • 可选择 vw:如果项目是纯粹的移动端页面(例如 App 内嵌 H5),或者对 PC 端浏览效果没有要求,vw 因其简单便捷而成为一个很好的选项。
  • % 作为补充:当需要一个子元素相对于其父元素进行缩放时,百分比是不可替代的。例如,一个宽度由JS动态计算的父容器,内部有两个子元素想按 3:7 比例分割,此时只能用 width: 30%width: 70%

六、其他注意事项

  1. 边距处理

    • 元素间的对齐和分布(如两端对齐),应使用 Flex 布局的 justify-content: space-between 等属性。
    • 元素与元素之间固定的间距,应使用 remvw 单位,如 margin-left: 0.2rem
  2. 图片处理

    • 为防止图片拉伸变形,通常设置 width: 100%; height: auto;
    • 为防止图片在PC大屏上被放得过大,可以为其容器或自身设置一个 max-width
  3. 大屏可视化项目

    • 这类项目通常要求严格铺满屏幕。当用户按 F11 进入全屏时,屏幕的高度会变化,但宽度不变
    • 这种情况下,基于宽度的 remvw 不会重新计算,可能导致布局问题。
    • 因此,在大屏项目中,对于高度需要严格适配的元素,可以考虑使用 vh 单位来定义,以响应高度的变化。