Skip to content

meta 视口设置

<meta name="viewport"> 标签是移动端 Web 开发的基础,它控制着浏览器在移动设备上如何渲染和缩放页面。没有正确的 viewport 设置,页面在手机上会以桌面版宽度显示,导致内容过小、需要手动缩放。

前置知识

阅读本节前,建议先了解:meta 字符编码

基础概念

什么是视口(Viewport)

视口是浏览器窗口中用于显示网页内容的区域。在桌面端,视口宽度通常等于浏览器窗口宽度。但在移动设备上,情况有所不同:

桌面端视口

  • 视口宽度 = 浏览器窗口宽度
  • 1 个 CSS 像素 = 1 个设备像素(不考虑缩放)

移动端视口

  • 有两个视口概念:布局视口(Layout Viewport)和视觉视口(Visual Viewport)
  • 布局视口:浏览器用于计算 CSS 布局的虚拟宽度,通常为 980px(默认值)
  • 视觉视口:用户在屏幕上实际看到的区域

没有 viewport 设置时的默认行为

当移动端浏览器打开一个没有 viewport 声明的页面时:

  1. 浏览器会将布局视口设为较大的固定宽度(通常 980px 或 1024px)
  2. 页面按照这个宽度进行布局
  3. 然后将整个页面缩小到适应屏幕宽度
  4. 用户看到的是缩小版的桌面页面,文字很小
html
<!-- 没有 viewport 设置 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>没有 viewport</title>
</head>
<body>
  <p>这个页面在手机上会显示得很小,需要手动放大。</p>
</body>
</html>

有 viewport 设置后的行为

html
<!-- 有 viewport 设置 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>有 viewport</title>
</head>
<body>
  <p>这个页面在手机上会以合适的宽度显示,文字清晰可读。</p>
</body>
</html>

语法

基本语法

html
<meta name="viewport" content="width=device-width, initial-scale=1.0">

viewport 属性详解

content 属性可以包含多个设置项,用逗号分隔:

属性说明
width正整数 或 device-width设置布局视口宽度
initial-scale0.1 ~ 10初始缩放比例
minimum-scale0.1 ~ 10最小缩放比例
maximum-scale0.1 ~ 10最大缩放比例
user-scalableyesno是否允许用户缩放
height正整数 或 device-height设置布局视口高度(很少使用)
viewport-fitauto / contain / cover适配安全区域(如刘海屏)

属性详细说明

width

html
<!-- 布局视口宽度等于设备宽度 -->
<meta name="viewport" content="width=device-width">

<!-- 布局视口宽度固定为 320px(不推荐) -->
<!-- <meta name="viewport" content="width=320"> -->
  • device-width 表示将布局视口宽度设为设备屏幕宽度
  • 也可以设置固定像素值,但不推荐,这违背了响应式设计的初衷
  • 这是响应式设计的最关键设置

initial-scale

html
<!-- 初始缩放比例为 1.0(不缩放) -->
<meta name="viewport" content="initial-scale=1.0">

<!-- 初始缩放比例为 0.5(缩小到 50%) -->
<!-- <meta name="viewport" content="initial-scale=0.5"> -->
  • 1.0 表示 100%,即不缩放
  • 0.5 表示 50%,页面会缩小到一半
  • 2.0 表示 200%,页面会放大到两倍
  • 推荐使用 1.0

minimum-scale 和 maximum-scale

html
<!-- 限制缩放范围在 0.5 ~ 2.0 之间 -->
<meta name="viewport" content="minimum-scale=0.5, maximum-scale=2.0">

<!-- 不推荐:禁止缩放 -->
<!-- <meta name="viewport" content="maximum-scale=1.0, user-scalable=no"> -->

无障碍警告

设置 user-scalable=nomaximum-scale=1.0 会禁止用户缩放页面,这违反了 WCAG 无障碍标准。对于视力不佳的用户,缩放是必要的辅助功能。除非有特殊需求(如类原生应用的 Web 页面),否则不应禁止缩放。

viewport-fit(安全区域适配)

html
<!-- 适配刘海屏等异形屏 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

viewport-fit 属性用于适配 iPhone X 等带有刘海屏或圆角的设备:

说明
auto(默认)不扩展到安全区域外
contain视口缩放以适应屏幕
cover视口扩展到整个屏幕,可能被刘海遮挡

配合 CSS 的 env() 函数使用:

css
/* 适配安全区域 */
body {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

详细说明

三种视口类型

视口类型英文说明
布局视口Layout Viewport浏览器用于 CSS 布局计算的宽度
视觉视口Visual Viewport用户在屏幕上实际看到的区域
理想视口Ideal Viewport布局视口 = 设备宽度,不需要缩放就能正常显示

常见设备宽度

设备设备宽度(CSS 像素)设备像素比(DPR)
iPhone SE375px2
iPhone 14390px3
iPhone 14 Pro Max430px3
iPad Mini768px2
iPad Pro 12.9"1024px2
Samsung Galaxy S23360px3
大多数 Android 手机360px ~ 412px2~3

完整的 viewport 推荐配置

html
<!-- 标准配置(适用于大多数网站) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- 完整配置(包含所有参数) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0, user-scalable=yes">

<!-- 适配刘海屏的配置 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

viewport 与响应式设计的关系

viewport 设置是响应式设计的前提条件。没有正确的 viewport,媒体查询将无法正常工作:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>响应式设计示例</title>
  <style>
    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }

    /* 桌面端:两列布局 */
    .grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20px;
    }

    /* 平板端:两列 */
    @media (max-width: 768px) {
      .grid {
        grid-template-columns: repeat(2, 1fr);
      }
    }

    /* 手机端:单列 */
    @media (max-width: 480px) {
      .grid {
        grid-template-columns: 1fr;
      }
    }

    .card {
      background: #f0f0f0;
      padding: 20px;
      border-radius: 8px;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>响应式网格布局</h1>
    <div class="grid">
      <div class="card">卡片 1</div>
      <div class="card">卡片 2</div>
      <div class="card">卡片 3</div>
      <div class="card">卡片 4</div>
      <div class="card">卡片 5</div>
      <div class="card">卡片 6</div>
    </div>
  </div>
</body>
</html>

viewport 设置的常见错误

1. 缺少 viewport 声明

html
<!-- 错误!移动端页面没有 viewport 设置 -->
<head>
  <meta charset="UTF-8">
  <title>我的网站</title>
</head>

2. 使用固定宽度

html
<!-- 不推荐!固定宽度无法适应不同设备 -->
<meta name="viewport" content="width=320">

<!-- 推荐 -->
<meta name="viewport" content="width=device-width">

3. 禁止用户缩放

html
<!-- 不推荐!影响无障碍性 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<!-- 推荐 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

4. 设置多个 viewport 标签

html
<!-- 错误!只能有一个 viewport 标签 -->
<meta name="viewport" content="width=device-width">
<meta name="viewport" content="initial-scale=1.0">

<!-- 正确:合并为一个 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

实战示例

viewport 信息查看器

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Viewport 信息查看器</title>
  <style>
    body {
      font-family: system-ui, sans-serif;
      margin: 0;
      padding: 20px;
      background: #f5f5f5;
      line-height: 1.6;
    }
    .info-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 15px;
      max-width: 600px;
      margin: 20px auto;
    }
    .info-card {
      background: white;
      border-radius: 8px;
      padding: 15px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .info-card h3 {
      margin: 0 0 8px;
      color: #666;
      font-size: 14px;
    }
    .info-card .value {
      font-size: 24px;
      font-weight: bold;
      color: #0066cc;
    }
    .info-card .unit {
      font-size: 14px;
      color: #999;
    }
    @media (max-width: 480px) {
      .info-grid {
        grid-template-columns: 1fr;
      }
    }
  </style>
</head>
<body>
  <h1 style="text-align:center;">Viewport 信息查看器</h1>
  <p style="text-align:center; color:#666;">
    缩放浏览器窗口或在不同设备上查看此页面
  </p>

  <div class="info-grid">
    <div class="info-card">
      <h3>窗口宽度 (window.innerWidth)</h3>
      <div class="value" id="win-width">-</div>
      <div class="unit">CSS 像素</div>
    </div>
    <div class="info-card">
      <h3>窗口高度 (window.innerHeight)</h3>
      <div class="value" id="win-height">-</div>
      <div class="unit">CSS 像素</div>
    </div>
    <div class="info-card">
      <h3>设备宽度 (screen.width)</h3>
      <div class="value" id="screen-width">-</div>
      <div class="unit">设备像素</div>
    </div>
    <div class="info-card">
      <h3>设备像素比 (devicePixelRatio)</h3>
      <div class="value" id="dpr">-</div>
      <div class="unit">倍</div>
    </div>
    <div class="info-card">
      <h3>物理宽度 (screen.width * DPR)</h3>
      <div class="value" id="physical-width">-</div>
      <div class="unit">物理像素</div>
    </div>
    <div class="info-card">
      <h3>布局视口宽度</h3>
      <div class="value" id="layout-width">-</div>
      <div class="unit">CSS 像素</div>
    </div>
  </div>

  <script>
    function updateInfo() {
      document.getElementById('win-width').textContent = window.innerWidth;
      document.getElementById('win-height').textContent = window.innerHeight;
      document.getElementById('screen-width').textContent = screen.width;
      document.getElementById('dpr').textContent = window.devicePixelRatio;
      document.getElementById('physical-width').textContent =
        screen.width * window.devicePixelRatio;
      document.getElementById('layout-width').textContent =
        document.documentElement.clientWidth;
    }

    updateInfo();
    window.addEventListener('resize', updateInfo);
  </script>
</body>
</html>

响应式图片与 viewport

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>响应式图片</title>
  <style>
    img {
      max-width: 100%;
      height: auto;
      display: block;
      margin: 20px auto;
    }
    .info {
      text-align: center;
      color: #666;
      font-family: system-ui, sans-serif;
      padding: 20px;
    }
  </style>
</head>
<body>
  <p class="info">
    当前视口宽度: <b id="viewport-width">-</b>px
  </p>

  <!-- 使用 srcset 和 sizes 根据视口宽度加载不同尺寸的图片 -->
  <img
    src="image-800.jpg"
    srcset="image-400.jpg 400w,
            image-800.jpg 800w,
            image-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, 800px"
    alt="响应式图片示例"
  >

  <script>
    function updateWidth() {
      document.getElementById('viewport-width').textContent =
        window.innerWidth;
    }
    updateWidth();
    window.addEventListener('resize', updateWidth);
  </script>
</body>
</html>

注意事项

1. viewport 只影响移动端行为

在桌面浏览器中,<meta name="viewport"> 通常不会产生明显效果。桌面浏览器的布局视口始终等于窗口宽度。

2. 不要为桌面页面添加 viewport

如果你的网站只有桌面版本,不需要添加 viewport 标签。但现代 Web 开发中,响应式设计已经成为标准,几乎所有网站都应该添加。

3. 双击缩放与 300ms 延迟

在移动端,user-scalable=yes 时,浏览器会检测双击缩放手势,这可能导致点击事件有约 300ms 的延迟。现代浏览器已通过 <meta name="viewport" content="width=device-width"> 消除了这个问题。

4. 横屏与竖屏

viewport 设置在横屏和竖屏切换时会自动更新。device-width 的值会随屏幕方向变化。

最佳实践

1. 每个页面都添加标准 viewport 声明

html
<meta name="viewport" content="width=device-width, initial-scale=1.0">

2. 不要禁止用户缩放

html
<!-- 不推荐 -->
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> -->

3. 如果需要适配刘海屏

html
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

配合 CSS env() 函数处理安全区域。

4. 使用 CSS 媒体查询做响应式适配

viewport 只是设置了正确的视口宽度,实际的响应式布局需要配合 CSS 媒体查询。

5. 测试多种设备宽度

使用浏览器的开发者工具模拟不同设备宽度,确保页面在各种尺寸下都能正常显示。

viewport 速查表

配置代码
标准配置<meta name="viewport" content="width=device-width, initial-scale=1.0">
禁止缩放..., maximum-scale=1.0, user-scalable=no(不推荐)
刘海屏适配..., viewport-fit=cover
限制缩放范围..., minimum-scale=0.5, maximum-scale=3.0

下一节

继续学习:meta 描述与关键词

参考链接