likes
comments
collection
share

前端兼容性问题 - 屏幕尺寸兼容

作者站长头像
站长
· 阅读数 2

写在前面

目录:

  • 当前现状
  • 解决方案
  • 模拟设备测试方案
  • 总结

当前现状

Android 设备情况

根据OpenSignal 在 2015 年 8 月发布的基础统计数据可以知道Andoroid的设备复杂度:ANDROID FRAGMENTATION VISUALIZED

前端兼容性问题 - 屏幕尺寸兼容

iOS 设备情况

苹果公司目前已推出42款iPhone型号:维基百科

前端兼容性问题 - 屏幕尺寸兼容

常见屏幕分辨率

下面列出桌面端、移动端、平板电脑端的一些常见的屏幕分辨率,更多屏幕分辨率查阅:屏幕尺寸大全

桌面端常见屏幕分辨率(显示器)

  1. 1280x720:720p,高清分辨率
  2. 1280x1024:常见于 4:3 屏幕比例的显示器
  3. 1366x768:现在非常常见的低分辨率显示器
  4. 1600x900:较高的分辨率,常见于中等尺寸显示器
  5. 1920x1080:1080p,全高清分辨率,现在非常常见,适用于大多数显示器
  6. 2560x1440:2K 分辨率,适用于较大尺寸或高质量显示器
  7. 3840x2160:4K 分辨率,适用于高端大尺寸显示器

移动端常见屏幕分辨率(智能手机)

  1. iPhone 6、iPhone 6s、iPhone 7、iPhone 8 和 iPhone SE(第二代)的分辨率
  2. 828x1792:iPhone XR 和 iPhone 11 的分辨率
  3. 1080x1920:许多 Android 设备的分辨率
  4. 1125x2436:iPhone X、iPhone XS 和 iPhone 11 Pro 的分辨率
  5. 1170x2532:iPhone 12 和 iPhone 12 Pro 的分辨率
  6. 1440x2560:许多高端 Android 设备的分辨率

平板电脑端常见屏幕分辨率

  1. 1536x2048:iPad 的 Retina 分辨率,如 iPad 3、iPad 4、iPad Air 和 iPad mini(2 代及以后)
  2. 1668x2224:iPad Air(第三代)和 iPad Pro 10.5 英寸
  3. 2048x2732:iPad Pro 12.9 英寸
  4. 800x1280:许多 Android 平板电脑的分辨率
  5. 1200x1920:许多高端 Android 平板电脑的分辨率

屏幕纵横比

统计以上的屏幕分辨率得出多端各自的主流纵横比

桌面端移动端平板电脑端
主流纵横比
  • 16 : 9
  • 16 : 10
  • 21 : 9
  • 19 : 9
  • 19.5 : 9
  • 16 : 9
  • 4 : 3
  • 16 : 9

解决方案

设置 meta 标签

先了解:viewport

viewport 表示浏览器中用来显示网页的可视区域。viewport 包括以下三种:

  1. layout viewport

layout viewport 为网页布局的区域,它是 html 元素的父容器,只要不在 css 中修改 元素的宽度, 元素的宽度就会撑满 layout viewport 的宽度。 很多时候浏览器窗口没有办法显示出 layout viewport 的全貌,但是它确实是已经被加载出来了,这个时候滚动条就出现了,你需要通过滚动条来浏览 layout viewport 其他的部分。 layout viewport 用 css 像素来衡量尺寸,在缩放、调整浏览器窗口的时候不会改变。缩放、调整浏览器窗口改变的只是 visual viewport。

在桌面浏览器中,缩放100% 的时候,Layout Viewport 宽度等于内容窗口的宽度。(你几乎不会在电脑上见过横向滚动条,除非你调整缩放) 但是在移动端,缩放为 100% 的时候,Layout Viewport 不一定等于内容窗口的大小。当你用手机浏览浏览宽大的网页(这些网页没有采用响应式设计)的时候,你只能一次浏览网页的一个部分,然后通过手指滑动浏览其他部分。这就说明整个网页已经加载出来了,只不过你要一部分一部分地看。

前端兼容性问题 - 屏幕尺寸兼容
  1. visual viewport

visual viewport 为视觉视口,就是显示在屏幕上的网页区域,它往往只显示 layout viewport 的一部分 visual viewport 就像一台摄像机,layout viewport 就像一张纸,摄像机对准纸的哪个部分,你就能看见哪个部分。你可以改变摄像机的拍摄区域大小(调整浏览器窗口大小),也可以调整摄像机的距离(调整缩放比例),这些方法都可以改变 visual viewport,但 layout viewport 始终不变

  1. ideal viewport

ideal viewport 为理想视口,不同的设备有自己不同的 ideal viewport,ideal viewport 的宽度等于移动设备的屏幕宽度,所以其是最适合移动设备的 viewport。只要在 css 中把某一元素的宽度设为 ideal viewport 的宽度(单位用 px ),那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100% 的效果。 ideal viewport 的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport 而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美的呈现给用户。

利用 meta 标签控制 viewport

移动设备默认的是 layout viewport,也就是那个比屏幕要宽的 viewport,但在进行移动端 H5 的开发时,我们需要的是 ideal viewport。那么怎么才能得到 ideal viewport 呢? 我们在开发 h5 页面时,最经常见的标签如下所示

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">

该 meta 标签的作用是让当前 viewport 的宽度等于设备的宽度,同时不允许用户手动缩放。如果你不这样的设定的话,那就会使用那个比屏幕宽的默认 viewport(layout viewport),也就是说会出现横向滚动条。 相关的属性意义如下所示:

属性描述
width设置 layout viewport 的宽度,为一个正整数,或字符串 "width-device"
height设置 layout viewport 的宽度,为一个正整数,或字符串 "height-device"
initial-scale设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale允许用户的最大缩放值,为一个数字,可以带小数
user-scalable是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes 代表允许

width=device-width 设置后 window.innerWidth 才等于 screen.width,否则 window.innerWidth 就是固定的宽度(例如谷歌浏览器是 980 px)

对比

页面在桌面端的预览效果

前端兼容性问题 - 屏幕尺寸兼容

在移动端的预览效果【左图没有设置 viewport,右图设置了 viewport】

前端兼容性问题 - 屏幕尺寸兼容 前端兼容性问题 - 屏幕尺寸兼容

媒体查询 @media

媒体查询是 CSS3 中的一项特性,允许我们根据设备的特定条件(如窗口或视口的宽度、高度、设备的方向、分辨率等)来应用不同的样式。这使得我们的网页在各种设备(桌面电脑、平板、手机等)和窗口大小上都有良好的显示和交互体验,也就是响应式设计的关键。

一个基本的媒体查询语法如下:

@media media_type and (media_feature) {
  /* 匹配时的 CSS 样式 */
}

其中:

  • media_type 是目标媒体设备的类型,如 screenprint 等。如果你不指定媒体类型,那意味着应用到所有媒体类型上(也就是 all)。
  • media_feature 是特定的设备特性,如 widthheight等。
  • and 用于将多个媒体特性合并在一起,所有条件必须匹配,样式才会被应用。

自适应单位

自适应单位包括 remvw 和百分比%

rem 单位

rem 是根据 根元素(html)字体大小 变化的相对单位。 rem 的全名是 root em,其值是相对于根元素的字体大小计算的。这意味着调整根元素的字体大小后,所有使用 rem 单位的元素都会自动调整。介绍如下:

  1. rem 是基于根元素(即 html 元素)字体大小计算的
  2. 计算公式:1 rem = 根元素字体大小

示例:

<!DOCTYPE html>
<html>
  <head>
    <style>
      html {
        font - size: 16px;
      }
      p {
        font - size: 1.25rem;
      }
    </style>
  </head>
  <body>
    <p>Hello, World!</p>
  </body>
</html>

在这个例子中,通过设置根元素字体大小为 16px,并为 <p> 元素设置颜色值为 1.25rem,计算出 <p> 的字体大小为 (16 * 1.25)px = 20px

vw、vh 单位

vw 是基于视口宽度的相对单位,vh 则是基于视口高度的相对单位。

视口的定义:web 页面能渲染的地方

其中 vwviewport width 的缩写。vw 单位是基于浏览器窗口宽度的相对度量,可以让元素自适应调整,无论设备大小。介绍如下:

  1. vw 是基于视口的宽度计算的
  2. 计算公式:1 vw = 视口宽度的1%

示例:

div {
  width: 50vw;
}

在这个例子中,将 <div> 的宽度设置为视口宽度的一半,即 50vw。如果视口宽度为 1200px<div> 的宽度为 (1200 * 50/100)px = 600px

rem 和 vw 的区别

  • "rem" 更适合用于字体大小、间距、边框等相对比较小的元素,因为这些元素大小的变化相对不会太大
  • "vw" 更适合用于相对于视口宽度而言较大的元素,例如页面的宽度或高度、容器的宽度

百分比 % 单位

百分比单位%是相对于其父元素的尺寸来定义的。这意味着元素会根据其父元素的尺寸变化。这种单位充分利用了可用空间,可以实现自适应设计。介绍如下:

  1. % 是基于父元素的尺寸计算的
  2. 计算公式:1% = 父元素尺寸的1%

示例:

<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        width: 800px;
      }
      div {
        width: 50%;
      }
    </style>
  </head>
  <body>
    <div>Hello, World!</div>
  </body>
</html>

在这个例子中,将 <div> 的宽度设置为其父元素(<body>)宽度的一半,即 50%。因此 <div> 的实际宽度是其父元素宽度的一半:(800 * 50/100)px = 400px

px 自动转换为 vw

设计师经常给宽度大小为 375px 或 750px 的视觉稿,单位是 px,手动转换起来就很头疼,所以可以采用社区提供的 postcss-px-to-viewport 插件,可以实现将单位 px 自动转换为 vw

  1. 安装插件
npm install postcss-px-to-viewport --save-dev
yarn add -D postcss-px-to-viewport
  1. 引入插件

我们项目用的是 React 框架 + umi 脚手架,所以参考 umi 官网文档 - API 之配置,使用 extraPostCSSPlugins 这个属性即可引入 postcss-px-to-viewport 插件

前端兼容性问题 - 屏幕尺寸兼容

  1. 参数配置

参数配置示例:(其他配置项参考官网)

import px2vw from 'postcss-px-to-viewport';

export default defineConfig({
  extraPostCSSPlugins: [
    px2vw({
      unitToConvert: 'px', // 要转化的单位
      viewportWidth: 750, // 视窗的宽度,可根据自己的需求调整(这里是以PC端为例)
      // viewportHeight: 1080, 		// 视窗的高度
      unitPrecision: 6, // 转换后的精度,即小数点位数
      propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
      viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
      fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
      // selectorBlackList: ['wrap'],// 指定不转换为视窗单位的类名,
      minPixelValue: 0.1, // 默认值1,小于或等于1px则不进行转换
      mediaQuery: false, // 是否在媒体查询的css代码中也进行转换,默认false
      replace: true, // 是否转换后直接更换属性值
      exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
      landscape: false, // 是否处理横屏情况
    }),
  ]
});
  1. 最终效果
.invalid {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: -80px;
  left: 0;
  font-size: 32px;
}

前端兼容性问题 - 屏幕尺寸兼容

响应式布局

flex 布局

参考 flex 布局的基本概念 - MDN 提供的定义:Flexible Box 模型,通常被称为 flexbox,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布对齐能力。我们说 flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列

grid 布局

参考 网格布局 - MDN 提供的定义:CSS 网格布局擅长于将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。像表格一样,网格布局让我们能够按行或列来对齐元素。然而在布局上,网格比表格更可能做到或更简单。例如,网格容器的子元素可以自己定位,以便它们像 CSS 定位的元素一样,真正的有重叠和层次。

模拟设备测试方案

模拟桌面端屏幕尺寸

  1. 打开 Chrome 浏览器控制台,打开设备工具栏(Ctrl+Shift+M)
前端兼容性问题 - 屏幕尺寸兼容
  1. 打开尺寸栏,选择【自适应】,拖动右下角即可随意设置屏幕尺寸宽高,模拟各种桌面端屏幕尺寸非常地简单。同时也可以直接输入宽高,更加精确
前端兼容性问题 - 屏幕尺寸兼容

模拟移动端设备

为了模拟多端设备的纵横比,同样可以利用控制台来模拟这些设备

  1. 打开尺寸栏,点击【修改】
前端兼容性问题 - 屏幕尺寸兼容
  1. 填写设备信息
前端兼容性问题 - 屏幕尺寸兼容
  1. 保存设备后即可快速模拟各端的纵横比(这里只举例三个)
前端兼容性问题 - 屏幕尺寸兼容

H5 会变“矮”?

细心的同学会发现:真机测试时在大多数移动端浏览器和 APP 端内打开的 H5 会变“矮”

Safari 浏览器移动端 为例,状态栏地址栏占用了大量高度

前端兼容性问题 - 屏幕尺寸兼容 前端兼容性问题 - 屏幕尺寸兼容

安卓系统真机自带的底部导航栏也会“挤掉” H5 的高度

前端兼容性问题 - 屏幕尺寸兼容

在移动端浏览器和 APP 端内有固定高度的状态栏、标题栏、地址栏、底部导航栏等,影响了视口高度,所以在真机中打开的 H5 的纵横比要实际小于上面计算出的纵横比,所以我们也要考虑到状态栏、标题栏、底部导航栏占掉的高度(特别是有一屏渲染的需求)

先模拟变“矮”效果

这里我推荐下载安装 微信开发者工具 来模拟真机效果

但是注意:微信开发者工具只能模拟出状态栏、标题栏、苹果的小黑条,但无法模拟出移动端浏览器的地址栏Android 底部导航栏

  1. 下载安装后打开微信开发者工具,选择公众号网页项目
前端兼容性问题 - 屏幕尺寸兼容
  1. 把本地 dev 运行的链接直接贴进去,即可同时看到控制台打印信息和模拟器

前端兼容性问题 - 屏幕尺寸兼容

  1. 自定义模拟器

同样的,我们也可以自定义模拟器的配置

前端兼容性问题 - 屏幕尺寸兼容

可以看到,所有的模拟器状态栏标题栏都占用了 H5 的高度

方案1:固定宽高比而非固定高度

开发 H5 的时候尽可能在固定宽度为 100vw 的前提下,让高度也是用 vw 做长度单位,这样是固定宽高比而非固定高度

如果非常有必要固定高度的话,建议采用以下两种方案:

方案2:用 100dvh 代替 100vh

动态视口单位:dvh

动态视口的意思是:

  1. 动态工具栏展开时,动态视口等于小视口的大小
  2. 当动态工具栏被缩回时,动态视口等于大视口的大小

前端兼容性问题 - 屏幕尺寸兼容

动态视口单位兼容性:

前端兼容性问题 - 屏幕尺寸兼容

代码

100vh 和 100dvh 对比,用对角线标记方块高度

100 vh

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>100vh 测试</title>
    <style>
      body {
        margin: 0;
        background-color: #eee;
      }
      .center-block {
        width: 100vw;
        height: 100vh; /* vh 单位 */
        background: linear-gradient(
          to top right,
          transparent 0%, transparent calc(50% - 2px),
          #000 50%,
          transparent calc(50% + 2px), transparent 100%
        );
      }
    </style>
  </head>

  <body>
    <div class="center-block"></div>
  </body>
</html>

100dvh

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>100dvh 测试</title>
    <style>
      body {
        margin: 0;
        background-color: #eee;
      }
      .center-block {
        width: 100vw;
        height: 100dvh; /* dvh 单位 */
        background: linear-gradient(
          to top right,
          transparent 0%, transparent calc(50% - 2px),
          #000 50%,
          transparent calc(50% + 2px), transparent 100%
        );
      }
    </style>
  </head>

  <body>
    <div class="center-block"></div>
  </body>
</html>

效果

Safari 浏览器移动端【左图 100vh,右图 100dvh】

前端兼容性问题 - 屏幕尺寸兼容 前端兼容性问题 - 屏幕尺寸兼容

Chrome 浏览器移动端【左图 100vh,右图 100dvh】

前端兼容性问题 - 屏幕尺寸兼容 前端兼容性问题 - 屏幕尺寸兼容

Android 系统浏览器【左图 100vh,右图 100dvh】

前端兼容性问题 - 屏幕尺寸兼容 前端兼容性问题 - 屏幕尺寸兼容

方案3:用 window.innerHeight 代替 100vh

考虑到动态视口单位 dvh 的兼容性较差,也可以借助 window.innerHeight 来代替 100vh

前端兼容性问题 - 屏幕尺寸兼容

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>window.innerHeight 测试</title>
    <style>
      body {
        margin: 0;
        background-color: #eee;
      }
      .center-block {
        width: 100vw;
        background: linear-gradient(
          to top right,
          transparent 0%, transparent calc(50% - 2px),
          #000 50%,
          transparent calc(50% + 2px), transparent 100%
        );
      }
    </style>
  </head>

  <body>
    <div id="center-block" class="center-block"></div>
  </body>

  <script>
    window.onload = () => {
      const dom = document.getElementById("center-block");
      dom.style.height = window.innerHeight + "px";
    };
  </script>
</html>

苹果系统兼容全屏 H5

苹果系统受圆角、齐刘海、小黑条影响,下图的蓝色区域是安全区域,灰色区域和红色区域是非安全区域

前端兼容性问题 - 屏幕尺寸兼容

注意:移动端浏览器和大多数的 APP 端已经把 H5 限制在安全区域内,就不需要 H5 去考虑这个问题了,我们要考虑的是少部分 APP 端内嵌入的 H5 可能会“触碰”到苹果系统的非安全区域

我们借助微信开发者工具模拟器可以模拟这样的场景:选择 iPhone X 及以上的苹果系统设备时,会发现 H5 “触碰”到苹果系统的小黑条区域

前端兼容性问题 - 屏幕尺寸兼容

先了解:viewport-fit 属性

iOS11 新增特性,苹果公司为了适配 iPhoneX 对现有 viewport meta 标签的一个扩展,用于设置网页在可视窗口的布局方式,可设置三个值。

  • contain: 可视窗口完全包含网页内容(左图)
  • cover:网页内容完全覆盖可视窗口(右图)
  • auto:默认值,跟 contain 表现一致

前端兼容性问题 - 屏幕尺寸兼容

需要注意:网页默认不添加扩展的表现是 viewport-fit=contain,需要适配 iPhoneX 必须设置 viewport-fit=cover,这是适配的关键步骤。更详细说明,参考文档:viewport-fit-descriptor

先了解:env()、constant() 函数

iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:

  • safe-area-inset-left:安全区域距离左边边界距离
  • safe-area-inset-right:安全区域距离右边边界距离
  • safe-area-inset-top:安全区域距离顶部边界距离
  • safe-area-inset-bottom:安全区域距离底部边界距离

这里我们只需要关注 safe-area-inset-bottom 这个变量,因为它对应的就是小黑条的高度(横竖屏时值不一样)。

注意:当 viewport-fit=contain 时 env() 是不起作用的,必须要配合 viewport-fit=cover 使用。对于不支持 env() 的浏览器,浏览器将会忽略它

需要注意的是之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我们还是需要做向后兼容,像这样:

padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */

注意:env() 跟 constant() 需要同时存在而且顺序不能换。 更详细说明,参考文档:Designing Websites for iPhone X

方案

  1. 新增 viweport-fit 属性,使得页面内容完全覆盖整个窗口
<meta name="viewport" content="width=device-width, viewport-fit=cover">
  1. 通过加内边距 padding 扩展高度:
{
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

注意,这个方案需要吸底条必须是有背景色的,因为扩展的部分背景是跟随外容器的,否则出现镂空情况。

还有一种方案就是,可以通过新增一个新的元素空的颜色块,主要用于小黑条高度的占位),然后吸底元素可以不改变高度只需要调整位置,像这样:

{
  margin-bottom: constant(safe-area-inset-bottom);
  margin-bottom: env(safe-area-inset-bottom);
}

空的颜色块:

{
  position: fixed;
  bottom: 0;
  width: 100%;
  height: constant(safe-area-inset-bottom);
  height: env(safe-area-inset-bottom);
  background-color: #fff;
}

总结

  1. 开发前:尽可能了解用户画像,包括操作系统(Windows、Mac、iOS、Android?)、访问设备(桌面端、移动端?),尽可能减少需要兼容的屏幕的范围
  2. 开发过程中:
    • 采用响应式设计 viewport
    • 采用媒体查询 @media
    • 采用自适应单位 rem、vw、%
    • 采用响应式布局 flex 布局、grid 布局
    • 考虑到真机视口高度变“矮”的情况,用 100dvh、window.innerHeight 代替 100vh
    • 如果 H5 触碰到苹果系统的非安全区,则需要借助 env()、constant() 函数留足安全距离
  3. 测试过程中:

拓展

一般来讲,为了减少代码的逻辑判断,我们会把桌面端和移动端分成两套前端代码,对应两域名

但如果我们只是单纯页面展示,可以考虑开发竖屏的 H5 后去兼容移动端横屏和桌面端屏幕 (桌面端屏幕 = 放大后的移动端横屏)

  • 方案一:设置最大宽度

适用场景:桌面端视图保持和移动端竖屏一致

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>max-width测试</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        margin: 0;
        width: 100vw;
        height: 100vh;
        background-color: #eee;
      }
      .center-block {
        width: 100vw;
        height: 100vh;
        max-width: 500px;
        background-color: aqua;
      }
    </style>
  </head>

  <body>
    <div class="center-block"></div>
  </body>
</html>

效果:【左图移动端竖屏,右图桌面端】

前端兼容性问题 - 屏幕尺寸兼容   前端兼容性问题 - 屏幕尺寸兼容
  • 方案二:vmin、vmax

适用场景:盒子永远居中不溢出屏幕

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vmin测试</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        margin: 0;
        width: 100vw;
        height: 100vh;
        background-color: #eee;
      }
      .center-block {
        width: 100vmin;
        height: 100vmin;
        background-color: aqua;
      }
    </style>
  </head>

  <body>
    <div class="center-block"></div>
  </body>
</html>

效果:【左图移动端竖屏,右图移动端横屏】

前端兼容性问题 - 屏幕尺寸兼容   前端兼容性问题 - 屏幕尺寸兼容

参考文章