在 Vue 项目中实现布局自适应,主要有 响应式布局 和 适配不同分辨率 两个层面的需求。
一、基本概念
1. 什么是布局自适应?
- 响应式:同一套代码,在不同设备上(手机、平板、PC)呈现不同的布局
- 适配:在不同分辨率的屏幕上,元素大小、间距能自动缩放
2. 技术方案选择
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| css3媒体查询 | 响应式布局 | 简单直观 | 需要写多套样式 |
| grid / flex | 弹性布局 | 灵活强大 | 复杂布局需经验 |
| rem/vw 方案 | 移动端适配 | 按比例缩放 | PC端体验不佳 |
| 第三方UI库 | 快速开发 | 优点 | 缺点 |
二、基础方案
1. CSS3 媒体查询
根据窗口大小调整布局,适合不同尺寸的桌面窗口。
vue
<template>
<div class="dashboard">
<div class="sidebar">侧边栏</div>
<div class="main-content">主内容</div>
</div>
</template>
<style scoped>
/* 手机:垂直排列 */
.dashboard {
display: flex;
flex-direction: column;
}
.sidebar {
width: 100%;
background: #f0f0f0;
}
.main-content {
width: 100%;
}
/* 平板及以上:水平排列 */
@media (min-width: 768px) {
.dashboard {
flex-direction: row;
}
.sidebar {
width: 250px;
}
.main-content {
flex: 1;
}
}
</style>
2. 弹性布局方案:Flex + Grid
(1) Flex 弹性布局
- 适合一维布局(横向或纵向排列)。
- 核心思路:使用 display: flex 让容器子元素按比例或自动填充。
vue
<template>
<div class="flex-demo">
<!-- 等宽排列 -->
<div class="flex-equal">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<!-- 响应式换行 -->
<div class="flex-wrap">
<div class="card" v-for="i in 10" :key="i">
卡片 {{ i }}
</div>
</div>
</div>
</template>
<style scoped>
/* 等宽布局 */
.flex-equal {
display: flex;
}
.flex-equal .item {
flex: 1; /* 平均分配剩余空间 */
text-align: center;
padding: 10px;
}
/* 响应式换行 */
.flex-wrap {
display: flex;
flex-wrap: wrap; /* 宽度不够时换行 */
gap: 16px; /* 间距 */
}
.flex-wrap .card {
flex: 1;
min-width: 200px; /* 最小宽度,小于此值会换行 */
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
}
</style>
(12) Grid 网格布局
- 适合二维布局(表格或复杂界面)。
- 可定义行列比例,自动填充。
- 适用场景:面板式应用、工具类桌面应用。
vue
<template>
<div class="grid-demo">
<!-- 自适应网格 -->
<div class="grid-auto">
<div v-for="i in 6" :key="i" class="grid-item">
项目 {{ i }}
</div>
</div>
</div>
</template>
<style scoped>
.grid-auto {
display: grid;
/* 自动填充,每个最小 250px,最大 1fr */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.grid-item {
background: #f0f0f0;
padding: 30px;
text-align: center;
border-radius: 8px;
}
/* 响应式调整列数 */
@media (max-width: 768px) {
.grid-auto {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 10px;
}
}
</style>
3. 响应式单位
(1) 百分比宽度/高度
.panel { width: 50%; height: 100%; }
(2) vw / vh(视口宽高单位)
- 50vw = 视口宽度的 50%
- 100vh = 视口高度
(3) rem / em(相对字体单位)
-
可以配合字体缩放实现组件缩放。
/* 设计稿上 100px 的元素,写 1rem /
.card {
width: 3.5rem; / 设计稿 350px /
padding: 0.2rem; / 设计稿 20px /
font-size: 0.28rem; / 设计稿 28px */
margin-bottom: 0.2rem;
}/* 边框可以使用 px */
.card {
border: 1px solid #eee;
}
总结
| 需求 | 推荐方案 |
|---|---|
| PC端后台系统 | Element Plus + Flex + 媒体查询 |
| 移动端 H5 | Vant + rem + vw |
| 复杂网格布局 | CSS Grid |
| 简单弹性布局 | Flexbox |