Vue 项目移动端适配怎么做?这套方案从 PC 到手机全搞定
响应式布局是现代 Web 开发的基础要求,但很多项目做得不够好。
PC 端好看,手机上一塌糊涂;或者用了 rem 适配,但字体大小在不同设备上还是不对。
这篇文章把 Vue 项目的移动端适配方案系统梳理一遍。
Tailwind CSS 响应式(推荐)
Tailwind 的响应式断点是目前最简洁的方案:
sm: 640px+md: 768px+lg: 1024px+xl: 1280px+2xl: 1536px+
<template> <!-- 移动端单列,平板双列,PC 三列 --> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div v-for="item in items" :key="item.id">{{ item.name }}</div> </div> <!-- 移动端隐藏,PC 显示 --> <aside class="hidden lg:block">侧边栏</aside> <!-- 移动端显示,PC 隐藏 --> <nav class="block lg:hidden">移动端导航</nav> <!-- 响应式字体 --> <h1 class="text-2xl md:text-3xl lg:text-4xl font-bold">标题</h1> <!-- 响应式间距 --> <div class="p-4 md:p-6 lg:p-8">内容</div></template>
自定义断点
// tailwind.config.jsexport default { theme: { screens: { xs: "375px", // 小手机 sm: "640px", md: "768px", lg: "1024px", xl: "1280px", }, },};
vw 适配(移动端 H5)
对于纯移动端 H5 页面,vw 适配是最简单的方案:
/* 以 375px 设计稿为基准 *//* 1vw = 3.75px,100vw = 375px */.container { width: 100vw; padding: 4vw; /* 15px */}.title { font-size: 4.8vw; /* 18px */}.button { height: 12vw; /* 45px */ font-size: 3.73vw; /* 14px */}
用 PostCSS 插件自动转换(推荐):
pnpm add -D postcss-px-to-viewport-8-plugin
// postcss.config.jsexport default { plugins: { "postcss-px-to-viewport-8-plugin": { viewportWidth: 375, // 设计稿宽度 unitPrecision: 5, viewportUnit: "vw", selectorBlackList: [".ignore", ".hairlines"], minPixelValue: 1, mediaQuery: false, }, },};
配置后,直接写 px,自动转换为 vw:
/* 写 px */.button { height: 45px; font-size: 14px;}/* 自动转换为 vw */.button { height: 12vw; font-size: 3.73333vw;}
useBreakpoints 检测屏幕尺寸
// composables/useBreakpoints.tsimport { useBreakpoints as vueUseBreakpoints } from "@vueuse/core";const breakpoints = vueUseBreakpoints({ xs: 375, sm: 640, md: 768, lg: 1024, xl: 1280,});export function useBreakpoints() { return { isMobile: breakpoints.smaller("md"), isTablet: breakpoints.between("md", "lg"), isDesktop: breakpoints.greaterOrEqual("lg"), current: breakpoints.active(), };}
<script setup> import { useBreakpoints } from "@/composables/useBreakpoints"; const { isMobile, isDesktop } = useBreakpoints();</script><template> <!-- 根据屏幕尺寸渲染不同组件 --> <MobileNav v-if="isMobile" /> <DesktopNav v-else /> <!-- 移动端显示简化版,PC 显示完整版 --> <SimpleTable v-if="isMobile" :data="data" /> <FullTable v-else :data="data" :columns="columns" /></template>
常见移动端坑点
1. 安全区域(刘海屏)
/* 处理 iPhone 刘海和底部 Home 条 */.header { padding-top: env(safe-area-inset-top);}.footer { padding-bottom: env(safe-area-inset-bottom);}/* Tailwind 写法 */
<template> <div class="pb-safe"> <!-- pb-safe 需要配置 Tailwind 插件 --> </div></template>
2. 1px 边框
/* 移动端 1px 边框(高清屏显示 2px 问题) */.border-1px { position: relative;}.border-1px::after { content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #e2e8f0; transform: scaleY(0.5); transform-origin: 0 100%;}
3. 点击延迟(300ms)
/* 消除移动端点击 300ms 延迟 */* { touch-action: manipulation;}
4. 禁止文字选中
/* 按钮等交互元素禁止文字选中 */.btn,.nav-item { user-select: none; -webkit-user-select: none;}
5. 滚动优化
/* 移动端流畅滚动 */.scroll-container { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; /* 防止滚动穿透 */}
6. 输入框被键盘遮挡
// 监听键盘弹出,滚动到输入框function handleFocus(event: FocusEvent) { const input = event.target as HTMLElement; setTimeout(() => { input.scrollIntoView({ behavior: "smooth", block: "center" }); }, 300);}
响应式图片
<template> <!-- 不同屏幕加载不同尺寸的图片 --> <picture> <source media="(min-width: 1024px)" srcset="/images/hero-lg.jpg" /> <source media="(min-width: 768px)" srcset="/images/hero-md.jpg" /> <img src="/images/hero-sm.jpg" alt="Hero" /> </picture> <!-- 或者用 Nuxt Image --> <NuxtImg src="/images/hero.jpg" sizes="100vw sm:50vw md:400px" format="webp" /></template>
写在最后
移动端适配没有银弹,选对方案很重要:
-
• PC + 移动端兼容:Tailwind 响应式断点,最简洁 -
• 纯移动端 H5:vw 适配 + PostCSS 自动转换 -
• 需要 JS 判断屏幕:VueUse 的 useBreakpoints
夜雨聆风