vh适配指南.md 5.9 KB

vh 适配指南 - 移动端高度敏感应用

适配原则

基于高度(vh)+ 基于宽度(vw)混合方案

纵向属性 → vh(基于高度 812px)
横向属性 → vw(基于宽度 375px,由 postcss 自动转换)

已完成改造的页面

✅ CSS 文件改造(完成)

  1. WelcomePage.css - 完全改造
  2. RegisterPage.css - 完全改造
  3. SharePage.css - 完全改造
  4. VideoIntroPage.css - 全屏视频,无需改造

⏳ TSX 内联样式改造(待完成)

以下页面使用内联样式,需要手动改造:

  1. ChatBotPage.tsx
  2. GreetingPage.tsx
  3. LumiNamingPage.tsx
  4. LoadingPage.tsx
  5. ErrorPage.tsx

改造方法

1. CSS 文件中的改造

❌ 改造前(全部使用 px,自动转 vw)

.element {
  top: 138px;      /* → 36.8vw (基于宽度)❌ */
  left: 45px;      /* → 12vw ✅ */
  width: 245px;    /* → 65.33vw ✅ */
  height: 113px;   /* → 30.13vw ❌ */
}

✅ 改造后(纵向用 vh,横向用 vw)

.element {
  top: 17vh;       /* 138 / 812 × 100 = 17vh ✅ */
  left: 45px;      /* → 12vw (自动转换) ✅ */
  width: 245px;    /* → 65.33vw (自动转换) ✅ */
  height: 13.92vh; /* 113 / 812 × 100 = 13.92vh ✅ */
}

计算公式

// 纵向属性(手动计算)
vh = (设计稿px / 812) × 100

// 横向属性(保持 px,自动转换)
vw = (设计稿px / 375) × 100  // postcss 自动处理

2. TSX 内联样式中的改造

❌ 改造前(全部使用 px2vw)

import { px2vw } from '@/utils/viewport';

<div style={{
  top: px2vw(138),      // ❌ 基于宽度
  left: px2vw(45),      // ✅ 正确
  width: px2vw(245),    // ✅ 正确
  height: px2vw(113),   // ❌ 基于宽度
}}>

✅ 改造后(纵向用 px2vh,横向用 px2vw)

import { px2vw, px2vh } from '@/utils/viewport';

<div style={{
  top: px2vh(138),      // ✅ 基于高度
  left: px2vw(45),      // ✅ 基于宽度
  width: px2vw(245),    // ✅ 基于宽度
  height: px2vh(113),   // ✅ 基于高度
}}>

属性分类速查表

纵向属性(使用 vh 或 px2vh)

  • top
  • bottom
  • height
  • min-height
  • max-height
  • padding-top
  • padding-bottom
  • margin-top
  • margin-bottom
  • line-height (特殊:建议用 vh)
  • gap (垂直方向)

横向属性(使用 vw 或 px2vw)

  • left
  • right
  • width
  • min-width
  • max-width
  • padding-left
  • padding-right
  • margin-left
  • margin-right
  • gap (水平方向)

特殊属性

  • font-size - 保持使用 vw(基于宽度更合理)
  • border-radius - 保持使用 vw(基于宽度)
  • box-shadow - 保持 px(不需要缩放)

实际案例

案例 1: WelcomePage - Hello 图片

设计稿: top: 138px, left: 45px, width: 245px, height: 113px

.welcome-hello {
  position: absolute;
  top: 17vh;      /* 138 / 812 = 17% */
  left: 45px;     /* → 12vw (自动) */
  width: 245px;   /* → 65.33vw (自动) */
  height: 13.92vh; /* 113 / 812 = 13.92% */
}

案例 2: RegisterPage - 输入框

设计稿: height: 56px

.register-input {
  height: 6.9vh; /* 56 / 812 = 6.9% */
  border-radius: 12px; /* → 3.2vw (自动) */
}

案例 3: ChatBotPage - 动态计算的内联样式

// ❌ 改造前
<div style={{
  height: px2vw(layout.avatarSize),
  marginTop: px2vw(layout.avatarMarginTop),
}}>

// ✅ 改造后
<div style={{
  height: px2vh(layout.avatarSize),
  marginTop: px2vh(layout.avatarMarginTop),
}}>

不同设备效果对比

iPhone 6/7/8 (375×667) - 矮屏

vw 方案: 700px → 186.67vw → 700px ❌ 超出屏幕
vh 方案: 700px → 86.2vh → 575px ✅ 自动适配

iPhone X/14 (375×812) - 标准屏

vw 方案: 700px → 186.67vw → 700px ✅ 符合设计稿
vh 方案: 700px → 86.2vh → 700px ✅ 完全符合设计稿

iPhone 14 Pro Max (393×926) - 高屏

vw 方案: 700px → 186.67vw → 733px ⚠️ 可能超出
vh 方案: 700px → 86.2vh → 798px ✅ 按比例放大

待改造页面清单

1. ChatBotPage.tsx

改造重点:

  • layout.avatarSize - 改用 px2vh
  • layout.avatarMarginTop - 改用 px2vh
  • layout.buttonBottomPosition - 改用 px2vh
  • 所有 height、top、bottom、padding-top/bottom 相关

2. GreetingPage.tsx

改造重点:

  • contentPaddingTop - 改用 px2vh
  • contentPaddingBottom - 改用 px2vh
  • sectionGap - 改用 px2vh
  • lineHeight - 改用 px2vh

3. LumiNamingPage.tsx

改造重点:

  • 类似 GreetingPage
  • 所有纵向 padding、margin、gap

4. LoadingPage.tsx & ErrorPage.tsx

改造重点:

  • 简单页面,优先级较低
  • 主要是居中元素的高度

验证清单

改造完成后,在以下设备上测试:

  • iPhone SE (375×667) - 矮屏
  • iPhone 6/7/8 (375×667) - 矮屏
  • iPhone X/11/12/14 (375×812) - 标准屏
  • iPhone 14 Pro Max (393×926) - 高屏
  • iPad (768×1024) - 平板

重点检查:

  1. 元素不会超出屏幕
  2. 比例保持一致
  3. 间距合理
  4. 无元素重叠

常见问题

Q: 为什么不全部用 vh?

A: 宽度变化小(375-393px),高度变化大(667-926px)。纵向用 vh 更合理。

Q: clamp() 怎么处理?

A: 如果使用了 clamp(min, preferred, max),preferred 值改为 vh:

/* 改造前 */
top: clamp(56px, 7vh, 64px);

/* 改造后(如果需要更严格) */
top: 6.9vh; /* 56 / 812 = 6.9vh */

Q: 100% 和 vh 的区别?

A:

  • 100% - 相对父元素
  • 100vh - 相对视口高度
  • 对于顶层容器,使用 100vh 更可靠

快速参考

设计稿值 vh 计算 结果
56px 56 / 812 × 100 6.9vh
138px 138 / 812 × 100 17vh
700px 700 / 812 × 100 86.2vh

在线计算器: (设计稿px / 812) × 100 = vh