Skip to content

响应式布局的主要实现方式(原生方式)

约 2787 字大约 9 分钟

响应式布局

2025-09-20

没有任何一种布局方案是完美的,根据不同的场景和需求,选择不同的技术组合、互相弥补缺点,才是最优的解决方案。

固定布局 (Fixed Layout)

在“响应式设计”这个概念出现之前,开发者们已经在尝试解决多设备浏览的问题。通常大家会将页面的主要内容部分设置为固定宽度(如 960px、1200px),并设置居中显示。

局限性

在不同设备上,要么显示不全出现横向滚动条,要么两侧有大片空白。这是最早期的、只为桌面端设计的方案。

移动端与桌面端分离

在移动互联网诞生的初期,移动端桌面端 确实是两个完全不同的东西,当时的主流做法是为手机单独制作移动版站点,判断用户是用的设备是移动端还是桌面端,重定向到对应的站点。

例如:百度首页,https://m.baidu.com/

const userAgent = navigator.userAgent;
// 典型的UA检测跳转代码
if (
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
    userAgent
  )
) {
  deviceType = "移动设备";
  isMobile = true;
  location.href = "https://m.baidu.com/";
} else {
  location.href = "https://www.baidu.com/";
}

液态布局、百分比布局 (Liquid Layout / Fluid Layout)

在使用文档流布局的年代,我们一般使用 百分比(%),而不是 像素(px) 来规定每个模块的宽度,让整个页面的布局能随着屏幕大小,进行 平滑伸缩

原理 就是,将 父元素的宽度和高度,按照百分比分配给子元素。父元素的尺寸变化时,子元素会自动变化,从而实现响应式布局。

缺点

百分比布局的缺陷很明显,就是需要进行 复杂的手动计算,以及处理 预期之外的错位

百分比的值是基于父元素的宽度来计算,这里边就牵扯到了盒模型和元素尺寸计算。如果使用统一的百分比还好,一旦使用的非百分比的单位(如 px),用来描述元素、文字的尺寸、边框、间距等,就可能会出现预期之外 换行、错位 等情况。

一般我们会针对这种场景多包裹一层 不含边框、间距 的容器,来解决这个问题。

弹性图片/媒体 (Flexible Images)

widthmax-widthmin-width等属性给的元素一定的弹性范围,可以使用固定值或者百分比在一定程度上实现响应式布局。

例如:

div {
  width: 100%;
  min-width: 320px;
  max-width: 1200px;
}

以上代码的作用:

  • 在父元素小于 320px 时,div 的宽度为 320px(因为 min-width 生效)
  • 在父元素介于 320px 和 1200px 之间时,div 的宽度为 100%,即随着视口宽度变化而变化
  • 在父元素大于 1200px 时,div 的宽度为 1200px(因为 max-width 生效)

媒体查询 (Media Queries)

媒体查询是 CSS 中一种非常重要的技术,它可以根据设备特性(如屏幕宽度、分辨率)应用不同的 CSS 样式。一般上,遵循 移动优先 的设计思路,先编写移动设备的样式,然后使用媒体查询,根据设备宽度,应用不同的样式。

/* 移动优先样式 (默认) */
.container {
  width: 100%;
}
/* 平板及以上 */
@media (min-width: 768px) {
  .container {
    width: 750px;
  }
}
/* 桌面及以上 */
@media (min-width: 992px) {
  .container {
    width: 970px;
  }
}

rem 方案(rem、em 单位)

Rem、Em 方案是基于 字体大小 来实现响应式布局的。通过对当前设备的宽度,动态地设置 HTML 根元素的字体大小,从而实现响应式布局。

  • rem 单位是相对于 根元素 的字体大小
  • em 单位是相对于 当前元素 的字体大小

淘宝的 lib-flexible 方案

在 Rem 时代,最主流的实现方案是淘宝的 lib-flexible 方案,它的主要实现步骤:

  1. 重置视口的宽度和缩放比例,禁止用户手动缩放
  2. 默认设计稿的宽度为 750px,按照设备宽度平均分配为 10 等份,每等份对应 75px,来生成根元素的字体大小。比如设备为 1000px,那么根元素的字体大小为 100px。
  3. 添加事件监听,当页面尺寸重置、窗口变化、加载时,动态计算根元素的字体大小
  4. 使用 rem、em 单位来描述元素、文字的尺寸、边框、间距等

现代进阶

现代项目中一般会使用 PostCSS 插件Sass/Less 函数,来将 px 单位转换为 rem 单位。

  • 优势: 我们无需进行手动计算,直接使用 px 来描述样式
  • 缺陷: 无法转换内联样式、JS 中设置的样式,可以使用 JS 对这些场景进行补充处理

rem 方案的优势

整体来说,Rem 方案的优势在于 简单、方便,只需要根据设计稿的宽度,计算出根元素的字体大小,然后使用 rem、em 单位来描述元素、文字的尺寸、边框、间距等,就可以实现响应式布局。

rem 方案的缺点

Rem 方案的虽然简单、方便,但是它同样存在一些缺点:

  1. 可能存在小数点导致的 计算误差,导致在不同设备上的显示效果和预期不符
  2. 如果设备的比例和设计图的比例不一致,可能导致屏幕上下、左右方向上 出现留白,无法 1:1 按照设计图还原

vw、vh 方案(vw、vh、vmin、vmax 单位)

vw、vh 方案是基于 视口宽度视口高度 来实现响应式布局的。主要有四个单位:

  • vw 单位是相对于 视口宽度 的百分比
  • vh 单位是相对于 视口高度 的百分比
  • vmin 单位是相对于 vwvh较小 的那个的百分比
  • vmax 单位是相对于 vwvh较大 的那个的百分比

我们可以通过手动计算,或者使用 Sass 函数、js 脚本,把 CSS、内联样式、js 中的 px 单位转换为 vw、vh 单位。

同样,也可以使用一些 PostCSS 插件,通过设置一些参数,如设计稿的尺寸、转换的目标单位等,来控制自动转换的行为和结果。以下是一个配置示例:

postcss.config.js
module.exports = {
  plugins: {
    // 其他 PostCSS 插件,例如 autoprefixer
    "postcss-px-to-viewport": {
      unitToConvert: "px", // 要转换的单位,默认为"px"
      viewportWidth: 375, // 设计稿的视口宽度,例如 iPhone 6/7/8 是 375
      unitPrecision: 5, // 转换后保留的小数位数
      propList: ["*"], // 指定要转换的属性,['*'] 表示所有属性都转换
      viewportUnit: "vw", // 转换后的视口单位
      fontViewportUnit: "vw", // 字体转换后的视口单位
      selectorBlackList: [], // 指定不转换的类,可以传入字符串或正则
      minPixelValue: 1, // 最小的转换像素值,小于等于此值的不转换
      mediaQuery: false, // 是否允许在媒体查询中转换 px
      exclude: [/node_modules/], // 忽略 node_modules 下的文件
      // 其他配置...
    },
  },
};

需要注意一点,PostCSS 无法处理内联样式、JS 中设置的样式,需要额外处理。

vw、vh 方案的优势

vw、vh 方案解决了 rem 方案留白的问题,可以完美适配各种不同尺寸比例的设备,包括移动端、平板、桌面端等,是当前比较主流的响应式布局方案。

弹性布局(Flexible Layout)

弹性布局(Flexible Layout),也被称为 flexbox,是一种用于 一维布局 的 CSS 布局模型。它允许你在容器中 灵活的分配对齐 子元素,而无需使用 float 或 position 等传统的布局技术。整体来说,flexbox 提供了一种更简单、更强大的方式来创建响应式布局,是当下响应式布局的首选方案之一。

缺点

flexbox 布局的缺点主要体现在 兼容性 上。虽然当下 flexbox 已经被主流设备和浏览器支持,但不排除有些用户的设备存在 兼容性问题。为了确保在所有浏览器中都能正常工作,可能需要使用 Babelpolyfillflexibility.js 等工具来添加对旧版浏览器的支持。

此外,flexbox 布局应对一些 二维布局 的场景,可能存在一些问题,可能需要结合其他一些技术解决。

表格布局(<table>

曾几何时,在那个没有网格布局的年代,表格布局是前端开发中一种常用的二维布局方式。表格布局通过使用 HTML 中的 <table> 元素和相关的 CSS 属性,将页面内容组织为 的网格结构。每个单元格可以包含文本、图片、表单元素等内容。

缺点

由于前端需要通过 js 来组装表格,在处理复杂的表格布局时,如动态控制行、列的生成、动态控制单元格数据、不规则异形表格等,可能需要非常复杂的 js 代码来处理。逐渐的语义化更强、灵活性更强的网格布局(Grid)代替。

网格布局(Grid Layout)

网格布局(Grid Layout),也被称为 表格布局,是一种用于 二维布局 的 CSS 布局模型。它允许你将页面划分为 ,并在这些网格中放置和对齐元素。网格布局提供了一种强大的方式来创建复杂的响应式布局,是当下响应式布局的另一种主流方案。

缩放(CSS3 transform)

在前端还有一种比较特殊的布局方式,就是 缩放(Viewport Scaling)。缩放布局是指根据设备的视口(viewport)大小,动态调整页面的缩放比例,以适应不同屏幕尺寸的设备。

通过使用 CSS3 中的 transform 属性,如 scale 函数,来实现元素的缩放。

// 使用JavaScript实现缩放响应式
function updateScale() {
  const container = document.getElementById("scaleContainer");
  const viewportWidth = window.innerWidth;
  const baseWidth = 1200; // 设计基准宽度
  const scale = Math.min(1, viewportWidth / baseWidth);
  container.style.transform = `scale(${scale})`;
  container.style.transformOrigin = "top center";
}

window.addEventListener("resize", updateScale);
window.addEventListener("load", updateScale);

优势

  • 实现简单:只需几行代码即可实现基本的响应式效果,无需编写复杂的媒体查询。
  • 保持布局比例:缩放可以完美保持原始设计的比例和布局,不会导致元素错位。
  • 开发速度快:对于固定尺寸的设计稿,可以快速实现响应式效果,节省开发时间。
  • 一致性:在所有设备上保持完全一致的外观和用户体验。

缺点

由于 css 的缩放只是视觉上的缩放,并没有改变元素的实际尺寸,所以在缩放时可能会导致页面的一些交互事件失效,如点击、滚动等。

更新日志

2025/9/27 17:16
查看所有更新日志
  • 1eb9b-docs(Javascript): 更新Generator生成器函数文档内容