Flexbox布局三剑客
flexbox布局的三大核心概念:
1. 方向(flex-direction)
flex-direction属性定义了主轴的方向,决定项目是水平排列还是垂直排列。
可选值:
- 
row(默认):主轴为水平方向,项目从左到右排列。
- 
row-reverse:主轴为水平方向,项目从右到左排列。
- 
column:主轴为垂直方向,项目从上到下排列。
- 
column-reverse:主轴为垂直方向,项目从下到上排列。
 示例代码:.box { 
 flex-direction: row | row-reverse | column | column-reverse;
 }

2. 主轴对齐属性(justify-content)
justify-content属性管理项目在主轴上的对齐和分布。
对齐类:
- 
flex-start(默认):项目向主轴起点对齐。
- 
flex-end:项目向主轴终点对齐。
- 
center:项目在主轴上居中对齐。
 分布类:
- 
space-between:项目均匀分布在主轴上,两端不留空隙。
- 
space-around:项目两侧间距相等,项目之间空隙是其他间隔的一半。
- 
space-evenly:所有项目之间的间隔完全相等,包括两端。
 示例代码:.box { 
 justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
 }
这样优化后的内容结构更清晰,描述更准确,方便读者理解和应用Flexbox布局。
3.交叉轴对齐(Align Items)
align-items 管理项目在交叉轴上的对齐方式。
- stretch (默认值)
 效果:拉伸所有 Flex 项目,使其在交叉轴方向上填满整个容器的高度。
条件:只有当项目没有设置固定高度(或 min-height / max-height)时,拉伸才会生效。如果项目设置了高度,则会使用该高度。
视觉表现:所有项目看起来都一样高,并且和容器一样高。
- flex-start
 效果:所有项目在交叉轴上紧贴容器起始点对齐。
视觉表现:项目从顶部开始排列,高度由自身内容或高度属性决定。
- flex-end
 效果:所有项目在交叉轴上紧贴容器结束点对齐。
视觉表现:项目从底部开始排列,高度由自身内容或高度属性决定。
- center
 效果:所有项目在交叉轴上居中对齐。
视觉表现:项目在垂直方向上居中,高度由自身内容或高度属性决定。这是非常常用的一个值。
- baseline
 效果:所有项目根据它们文本的基线进行对齐。
视觉表现:无论每个项目的高度是否相同,它们的文字都会在同一水平线上对齐。这对于对齐不同字体大小的文本内容非常有用。
实战一下
掌握了基础知识,我们来个小案例实践以下,我们现在要制作如下的效果,想让他拥有一定的自适应,又不会变形很严重,应该怎么制作呢?

整体布局结构
- 使用嵌套 flex布局实现两行四列的卡片布局
- 外层容器垂直排列,内层容器水平排列
主要布局代码分析
1. 外层容器 card-container
        .card-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px;
  width: 100%;
  box-sizing: border-box;
}- display: flex+- flex-direction: column: 创建垂直方向的弹性布局
- gap: 16px: 设置子元素(两行)之间的垂直间距
- padding: 20px: 容器内边距,确保内容不贴边
- box-sizing: border-box: 盒模型计算包含padding和border
2. 行容器 card-row
        .card-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 16px;
  width: 100%;
}- display: flex: 创建水平方向的弹性布局
- flex-wrap: nowrap: 禁止换行,强制所有卡片在一行内显示
- gap: 16px: 设置卡片间的水平间距
- width: 100%: 占满父容器宽度
3. 卡片项 card-item
        .card-item {
  flex: 1 1 calc(25% - 12px);
  min-width: 300px;
}- flex: 1 1 calc(25% - 12px):
- 
- flex-grow: 1: 有剩余空间时可以放大
- flex-shrink: 1: 空间不足时可以缩小
- flex-basis: calc(25% - 12px): 初始宽度为25%减去间隙占用空间
 
- min-width: 300px: 设置最小宽度,防止卡片过小
HTML结构说明
<template>
  <div class="card-container">
    <!-- 第一行 -->
    <div class="card-row">
      <div v-for="card in cardList.slice(0, 4)" :key="card.id" class="card-item">
        <!-- 卡片内容 -->
      </div>
    </div>
    <!-- 第二行 -->
    <div class="card-row">
      <div v-for="card in cardList.slice(4, 8)" :key="card.id" class="card-item">
        <!-- 卡片内容 -->
      </div>
    </div>
  </div>
</template>- cardList.slice(0, 4): 取前4个卡片用于第一行
- cardList.slice(4, 8): 取后4个卡片用于第二行
- 每行独立的 card-row容器确保两行布局的稳定性
这种布局方式在 flex-wrap: nowrap 的约束下实现了稳定的两行四列布局,并具有良好的响应式特性。
完整代码
<!-- FlexLab.vue -->
<script setup lang="ts">
  interface CardItem {
    id: number;
    title: string;
    description: string;
  }
  const cardList: CardItem[] = [
    { id: 1, title: '卡片一', description: '第一个功能卡片' },
    { id: 2, title: '卡片二', description: '第二个功能卡片' },
    { id: 3, title: '卡片三', description: '第三个功能卡片' },
    { id: 4, title: '卡片四', description: '第四个功能卡片' },
    { id: 5, title: '卡片五', description: '第五个功能卡片' },
    { id: 6, title: '卡片六', description: '第六个功能卡片' },
    { id: 7, title: '卡片七', description: '第七个功能卡片' },
    { id: 8, title: '卡片八', description: '第八个功能卡片' }
  ];
</script>
<template>
  <div class="card-container">
    <!-- 第一行 -->
    <div class="card-row">
      <div
        v-for="card in cardList.slice(0, 4)"
        :key="card.id"
        class="card-item"
        >
        <h3 class="card-title">{{ card.title }}</h3>
        <p class="card-description">{{ card.description }}</p>
      </div>
    </div>
    <!-- 第二行 -->
    <div class="card-row">
      <div
        v-for="card in cardList.slice(4, 8)"
        :key="card.id"
        class="card-item"
        >
        <h3 class="card-title">{{ card.title }}</h3>
        <p class="card-description">{{ card.description }}</p>
      </div>
    </div>
  </div>
</template>
<style scoped>
  .card-container {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 20px;
    width: 100%;
    box-sizing: border-box;
  }
  .card-row {
    display: flex;
    flex-wrap: nowrap;
    gap: 16px;
    width: 100%;
  }
  .card-item {
    flex: 1 1 calc(25% - 12px);
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 12px;
    padding: 20px;
    color: white;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
    box-sizing: border-box;
    min-width: 300px;
  }
  .card-item:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2);
  }
  .card-title {
    font-size: 18px;
    margin-bottom: 8px;
    font-weight: 600;
  }
  .card-description {
    font-size: 14px;
    opacity: 0.9;
  }
</style>