Skip to content

移动端适配

VitePress 默认主题已内置基本的响应式支持,但生产环境中的移动端体验仍需针对性优化。本文介绍如何系统性地适配移动端。

视口配置

基础视口设置

VitePress 默认已在主题中配置了视口,如需自定义,在配置中添加:

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=5' }]
  ]
})

禁止缩放(不推荐)

注意

禁止用户缩放会影响可访问性,仅在特殊场景下使用。

ts
// 仅在特定场景使用
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' }]

主题色配置

移动浏览器会根据 theme-color 调整 UI 颜色:

ts
export default defineConfig({
  head: [
    ['meta', { name: 'theme-color', content: '#ffffff' }],
    // 深色模式需要动态切换(见下文)
  ]
})

在主题入口动态切换主题色:

ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { useData, watch } from 'vitepress'

export default {
  extends: DefaultTheme,
  setup() {
    const { isDark } = useData()

    watch(isDark, (dark) => {
      const meta = document.querySelector('meta[name="theme-color"]')
      if (meta) {
        meta.setAttribute('content', dark ? '#1b1b1f' : '#ffffff')
      }
    }, { immediate: true })
  }
}

响应式布局

CSS 断点约定

VitePress 默认主题使用的断点:

断点宽度说明
移动端< 640px手机竖屏
平板640px - 959px平板竖屏
桌面≥ 960px桌面浏览器
宽屏≥ 1440px大屏幕

自定义响应式样式

css
/* .vitepress/theme/styles/responsive.css */

/* 移动端隐藏侧边栏辅助信息 */
@media (max-width: 639px) {
  .sidebar-helper {
    display: none;
  }
}

/* 平板端调整内容间距 */
@media (min-width: 640px) and (max-width: 959px) {
  .content-container {
    padding: 0 24px;
  }
}

/* 桌面端宽内容 */
@media (min-width: 960px) {
  .content-container {
    max-width: 900px;
  }
}

首页响应式定制

css
/* 移动端首页 Hero 文字大小 */
@media (max-width: 639px) {
  .VPHero .name {
    font-size: 2rem !important;
  }

  .VPHero .text {
    font-size: 1.25rem !important;
  }

  .VPHero .tagline {
    font-size: 0.95rem !important;
  }
}

Features 网格响应式

VitePress 首页 Features 默认 3 列,移动端自动调整为单列。如需自定义:

css
/* 平板 2 列 */
@media (min-width: 640px) and (max-width: 959px) {
  .VPFeatures .items {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}

触控优化

触控目标尺寸

确保可点击元素满足最小触控尺寸(48×48px):

css
/* 增大导航链接触控区域 */
.VPNav .link {
  padding: 8px 12px;
  min-height: 48px;
  display: flex;
  align-items: center;
}

/* 增大侧边栏链接触控区域 */
.VPSidebar .link {
  padding: 8px 16px;
  min-height: 44px;
}

触控反馈

css
/* 按钮触控反馈 */
.vp-button {
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.15s ease;
}

.vp-button:active {
  background-color: var(--vp-c-brand-soft);
}

滚动优化

css
/* 平滑滚动 */
html {
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}

/* 移动端侧边栏滚动优化 */
.VPSidebar {
  overscroll-behavior: contain;
}

移动端性能

图片优化

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    // 预连接图片 CDN
    ['link', { rel: 'preconnect', href: 'https://images.example.com' }]
  ]
})

在 Markdown 中使用响应式图片:

html
<picture>
  <source srcset="/images/hero-mobile.webp" media="(max-width: 639px)">
  <source srcset="/images/hero-tablet.webp" media="(max-width: 959px)">
  <img src="/images/hero-desktop.webp" alt="Hero 图片" loading="lazy">
</picture>

代码块移动端优化

VitePress 默认对代码块做了水平滚动处理。进一步优化:

css
/* 代码块移动端优化 */
.vp-code {
  font-size: 13px;
  -webkit-text-size-adjust: 100%;
}

/* 长代码块添加滚动提示 */
.vp-code-group {
  position: relative;
}

.vp-code-group::after {
  content: '→';
  position: absolute;
  right: 8px;
  top: 8px;
  opacity: 0.3;
  pointer-events: none;
}

@media (min-width: 640px) {
  .vp-code-group::after {
    display: none;
  }
}

减少移动端动画

css
/* 尊重用户偏好:减少动画 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

iOS 适配

安全区域

适配 iPhone 刘海屏和底部安全区域:

css
/* 适配安全区域 */
.VPNav {
  padding-top: env(safe-area-inset-top);
}

.VPFooter {
  padding-bottom: env(safe-area-inset-bottom);
}

.VPSidebar {
  padding-bottom: env(safe-area-inset-bottom);
}

禁止文字大小调整

iOS Safari 会自动调整文字大小,可能导致布局异常:

css
body {
  -webkit-text-size-adjust: 100%;
}

处理 iOS 弹性滚动

css
/* 防止 iOS 弹性滚动导致的布局问题 */
html, body {
  overscroll-behavior: none;
}

/* 侧边栏允许弹性滚动但不影响主内容 */
.VPSidebar {
  overscroll-behavior-y: contain;
}

Android 适配

地址栏颜色

Chrome Android 支持通过 meta 标签自定义地址栏颜色:

ts
export default defineConfig({
  head: [
    ['meta', { name: 'theme-color', content: '#ffffff' }]
  ]
})

PWA 支持

为移动端添加 PWA 支持,实现离线访问和添加到主屏幕:

ts
// .vitepress/config.mts
import { withPwa } from '@vite-pwa/vitepress'

export default withPwa(defineConfig({
  pwa: {
    registerType: 'autoUpdate',
    manifest: {
      name: 'VitePress 学习指南',
      short_name: 'VP 指南',
      theme_color: '#6366f1',
      icons: [
        {
          src: '/pwa-192x192.png',
          sizes: '192x192',
          type: 'image/png'
        },
        {
          src: '/pwa-512x512.png',
          sizes: '512x512',
          type: 'image/png'
        }
      ]
    }
  }
}))

详见

完整的 PWA 配置请参考 PWA 最佳实践PWA 代码配方

移动端测试

Chrome DevTools 模拟

  1. 打开开发者工具(F12)
  2. 点击设备模拟按钮(Ctrl+Shift+M)
  3. 选择设备或自定义尺寸

常用测试设备

设备宽度高度DPR
iPhone SE3756672
iPhone 143908443
iPhone 14 Pro Max4309323
iPad76810242
iPad Pro102413662
Pixel 74129152.625
Galaxy S233607803

真机调试

bash
# 使用 Vite 的 host 选项允许局域网访问
vitepress dev docs --host

# 输出类似:
#   ➜  Local:   http://localhost:5173/
#   ➜  Network: http://192.168.1.100:5173/

在手机浏览器中访问 Network 地址即可调试。

自动化测试

使用 Playwright 进行移动端自动化测试:

ts
// tests/mobile.spec.ts
import { test, expect } from '@playwright/test'

test.use({
  viewport: { width: 375, height: 667 },
  isMobile: true
})

test('移动端导航菜单可展开', async ({ page }) => {
  await page.goto('/')
  // 点击汉堡菜单
  await page.click('.VPNavBarHamburger')
  // 验证侧边栏可见
  await expect(page.locator('.VPSidebar')).toBeVisible()
})

test('移动端代码块可水平滚动', async ({ page }) => {
  await page.goto('/basics/markdown')
  // 验证代码块可滚动
  const codeBlock = page.locator('.vp-code').first()
  await expect(codeBlock).toBeVisible()
})

常见问题

移动端侧边栏闪现

在页面加载时侧边栏可能短暂闪现,添加以下 CSS:

css
/* 防止移动端侧边栏闪现 */
@media (max-width: 959px) {
  .VPSidebar {
    opacity: 0;
    transition: opacity 0.25s ease;
  }

  .VPSidebar.open {
    opacity: 1;
  }
}

移动端字体过大

iOS Safari 有时会自动调大字体,添加:

css
body {
  -webkit-text-size-adjust: 100%;
}

移动端 100vh 问题

移动端浏览器的 100vh 包含地址栏高度,使用 dvh 修复:

css
.VPHero {
  /* 现代浏览器 */
  height: 100dvh;
  /* 回退方案 */
  height: calc(var(--vh, 1vh) * 100);
}
ts
// .vitepress/theme/composables/useViewportHeight.ts
import { onMounted, onUnmounted } from 'vue'

export function useViewportHeight() {
  const setVH = () => {
    document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`)
  }

  onMounted(() => {
    setVH()
    window.addEventListener('resize', setVH)
  })

  onUnmounted(() => {
    window.removeEventListener('resize', setVH)
  })
}

检查清单

  • [ ] 视口 meta 标签已配置
  • [ ] 主题色已配置(含深色模式)
  • [ ] 触控目标尺寸 ≥ 44px
  • [ ] 代码块移动端可水平滚动
  • [ ] 图片使用响应式加载
  • [ ] iOS 安全区域已适配
  • [ ] 禁止文字大小自动调整
  • [ ] 至少在 3 种设备尺寸下测试
  • [ ] 已处理 prefers-reduced-motion
  • [ ] PWA manifest 已配置(可选)

参考链接

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献