Skip to content

响应式 Flexbox:打造自适应的现代布局

想象你在设计一个可以变形的家具。在小公寓里,它是一张单人沙发;在中等大小的客厅里,它可以展开成双人沙发;在宽敞的大厅里,它可以进一步展开成三人沙发。这种灵活适应空间的能力,正是响应式设计的核心理念。

Flexbox 天生就是为灵活布局而设计的。它的"弹性"不仅体现在单一屏幕尺寸下的空间分配,更体现在适应不同屏幕尺寸的能力上。结合媒体查询,Flexbox 可以让你轻松创建真正的响应式布局。

响应式设计的核心概念

在深入 Flexbox 的响应式应用之前,我们先理解几个核心概念。

断点(Breakpoints)

断点是指在不同屏幕尺寸下,布局发生变化的临界点。常用的断点通常基于设备类型:

css
/* 常用断点 */
/* 移动设备(手机) */
@media (max-width: 480px) {
}

/* 平板设备(竖屏) */
@media (min-width: 481px) and (max-width: 768px) {
}

/* 平板设备(横屏)和小屏笔记本 */
@media (min-width: 769px) and (max-width: 1024px) {
}

/* 桌面设备 */
@media (min-width: 1025px) {
}

但是,现代响应式设计推荐基于内容而不是设备来设置断点。如果你的布局在某个尺寸下开始变得拥挤或难看,那就是设置断点的时机。

移动优先(Mobile First)

移动优先是一种设计策略:先为最小的屏幕设计,然后逐步增强为更大的屏幕。

css
/* 移动优先的做法 */
.container {
  /* 基础样式:移动端 */
  display: flex;
  flex-direction: column;
}

/* 然后逐步增强 */
@media (min-width: 768px) {
  .container {
    flex-direction: row;
  }
}

为什么移动优先?

  1. 更好的性能:移动设备通常性能较弱,先优化移动端可以确保基础体验
  2. 渐进增强:从简单到复杂,更容易管理
  3. 强制优先级:迫使你思考什么是真正重要的内容

响应式导航栏

导航栏是最常见的响应式组件之一。在桌面端是水平排列,在移动端通常需要变成垂直排列或汉堡菜单。

基础响应式导航

html
<nav class="navbar">
  <div class="nav-brand">
    <div class="logo">TechCorp</div>
    <button class="menu-toggle" aria-label="Toggle menu">☰</button>
  </div>

  <ul class="nav-menu">
    <li><a href="#home">Home</a></li>
    <li><a href="#products">Products</a></li>
    <li><a href="#services">Services</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
  </ul>

  <div class="nav-actions">
    <button class="btn-login">Login</button>
    <button class="btn-signup">Sign Up</button>
  </div>
</nav>
css
/* 移动端优先 */
.navbar {
  display: flex;
  flex-direction: column; /* 移动端垂直排列 */
  padding: 15px 20px;
  background-color: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.nav-brand {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo {
  font-size: 22px;
  font-weight: bold;
  color: #2196f3;
}

.menu-toggle {
  display: block; /* 移动端显示菜单按钮 */
  padding: 8px 12px;
  background: none;
  border: 2px solid #2196f3;
  border-radius: 4px;
  font-size: 24px;
  cursor: pointer;
  color: #2196f3;
}

.nav-menu {
  display: none; /* 移动端默认隐藏 */
  flex-direction: column;
  gap: 0;
  list-style: none;
  margin: 15px 0 0 0;
  padding: 0;
}

.nav-menu.active {
  display: flex; /* 点击后显示 */
}

.nav-menu li a {
  display: block;
  padding: 12px 15px;
  color: #333;
  text-decoration: none;
  border-bottom: 1px solid #eee;
  transition: background-color 0.3s;
}

.nav-menu li a:hover {
  background-color: #f5f5f5;
}

.nav-actions {
  display: flex;
  flex-direction: column; /* 移动端按钮垂直排列 */
  gap: 10px;
  margin-top: 15px;
}

.btn-login,
.btn-signup {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.3s;
}

.btn-login {
  background-color: transparent;
  color: #2196f3;
  border: 2px solid #2196f3;
}

.btn-signup {
  background-color: #2196f3;
  color: white;
}

/* 平板和桌面端 */
@media (min-width: 768px) {
  .navbar {
    flex-direction: row; /* 水平排列 */
    align-items: center;
    justify-content: space-between;
    padding: 15px 40px;
  }

  .menu-toggle {
    display: none; /* 隐藏菜单按钮 */
  }

  .nav-menu {
    display: flex; /* 始终显示 */
    flex-direction: row; /* 水平排列 */
    gap: 25px;
    margin: 0;
  }

  .nav-menu li a {
    padding: 8px 15px;
    border-bottom: none;
    border-radius: 4px;
  }

  .nav-menu li a:hover {
    background-color: #e3f2fd;
  }

  .nav-actions {
    flex-direction: row; /* 水平排列按钮 */
    margin-top: 0;
    gap: 15px;
  }
}

这个导航栏在移动端是垂直布局,点击菜单按钮显示/隐藏。在平板和桌面端自动变成水平布局,菜单始终可见。

高级响应式导航

对于更复杂的导航,我们可能需要更多的控制:

css
/* 移动端:320px - 767px */
.navbar {
  display: flex;
  flex-wrap: wrap;
  padding: 12px 20px;
}

.nav-brand {
  flex: 0 0 100%; /* 占据整行 */
  display: flex;
  justify-content: space-between;
  margin-bottom: 15px;
}

.nav-menu,
.nav-actions {
  flex: 0 0 100%; /* 各占一行 */
}

/* 平板端:768px - 1023px */
@media (min-width: 768px) {
  .navbar {
    flex-wrap: nowrap; /* 不换行 */
  }

  .nav-brand {
    flex: 0 0 auto; /* 自适应宽度 */
    margin-bottom: 0;
  }

  .nav-menu {
    flex: 1 1 auto; /* 占据剩余空间 */
    justify-content: center;
  }

  .nav-actions {
    flex: 0 0 auto; /* 自适应宽度 */
  }
}

/* 大屏桌面端:1024px+ */
@media (min-width: 1024px) {
  .navbar {
    padding: 15px 60px; /* 更大的内边距 */
  }

  .nav-menu {
    gap: 35px; /* 更大的间距 */
  }
}

响应式卡片网格

卡片网格是最能展现 Flexbox 响应式能力的场景之一。

自适应列数

html
<div class="card-grid">
  <div class="card">
    <img src="product1.jpg" alt="Product" />
    <h3>Wireless Headphones</h3>
    <p>Premium sound quality</p>
    <span class="price">$299</span>
    <button>Add to Cart</button>
  </div>
  <!-- 更多卡片... -->
</div>
css
/* 移动端:1 列 */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 20px;
}

.card {
  flex: 1 1 100%; /* 占据 100% 宽度 */
  min-width: 0; /* 允许缩小 */
  display: flex;
  flex-direction: column;
  background-color: white;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.card img {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.card h3 {
  padding: 20px 20px 10px;
  margin: 0;
  font-size: 18px;
}

.card p {
  flex: 1; /* 占据剩余空间 */
  padding: 0 20px 15px;
  margin: 0;
  color: #666;
}

.price {
  padding: 0 20px;
  font-size: 24px;
  font-weight: bold;
  color: #2196f3;
}

.card button {
  margin: 15px 20px 20px;
  padding: 12px;
  background-color: #2196f3;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

/* 平板端:2 列 */
@media (min-width: 600px) {
  .card {
    flex: 1 1 calc(50% - 10px); /* 每行 2 张卡片,减去 gap */
  }
}

/* 桌面端:3 列 */
@media (min-width: 900px) {
  .card {
    flex: 1 1 calc(33.333% - 14px); /* 每行 3 张卡片 */
  }
}

/* 大屏幕:4 列 */
@media (min-width: 1200px) {
  .card {
    flex: 1 1 calc(25% - 15px); /* 每行 4 张卡片 */
  }
}

这个网格会根据屏幕宽度自动调整列数:

  • 移动端:1 列
  • 平板端:2 列
  • 桌面端:3 列
  • 大屏幕:4 列

混合尺寸的卡片

有时候我们需要不同尺寸的卡片来突出重要内容:

css
.card-featured {
  flex: 1 1 100%; /* 特色卡片始终占据整行 */
}

/* 平板端以上 */
@media (min-width: 600px) {
  .card-featured {
    flex: 1 1 100%; /* 特色卡片仍然占据整行 */
  }

  .card {
    flex: 1 1 calc(50% - 10px);
  }
}

/* 桌面端 */
@media (min-width: 900px) {
  .card-featured {
    flex: 1 1 calc(66.666% - 14px); /* 占据 2/3 宽度 */
  }

  .card {
    flex: 1 1 calc(33.333% - 14px);
  }
}

响应式表单布局

表单在不同设备上需要不同的布局。在移动端,字段通常应该垂直堆叠;在桌面端,可以并排显示。

html
<form class="responsive-form">
  <div class="form-row">
    <div class="form-group">
      <label for="firstName">First Name</label>
      <input type="text" id="firstName" required />
    </div>
    <div class="form-group">
      <label for="lastName">Last Name</label>
      <input type="text" id="lastName" required />
    </div>
  </div>

  <div class="form-row">
    <div class="form-group">
      <label for="email">Email</label>
      <input type="email" id="email" required />
    </div>
    <div class="form-group">
      <label for="phone">Phone</label>
      <input type="tel" id="phone" />
    </div>
  </div>

  <div class="form-row">
    <div class="form-group form-group-full">
      <label for="address">Address</label>
      <input type="text" id="address" />
    </div>
  </div>

  <div class="form-row">
    <div class="form-group">
      <label for="city">City</label>
      <input type="text" id="city" />
    </div>
    <div class="form-group">
      <label for="state">State</label>
      <input type="text" id="state" />
    </div>
    <div class="form-group">
      <label for="zip">ZIP</label>
      <input type="text" id="zip" />
    </div>
  </div>

  <div class="form-actions">
    <button type="button" class="btn-secondary">Cancel</button>
    <button type="submit" class="btn-primary">Submit</button>
  </div>
</form>
css
/* 移动端 */
.responsive-form {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.form-row {
  display: flex;
  flex-direction: column; /* 移动端垂直堆叠 */
  gap: 15px;
  margin-bottom: 20px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-group label {
  font-weight: 600;
  font-size: 14px;
  color: #333;
}

.form-group input {
  padding: 12px 15px;
  border: 2px solid #e0e0e0;
  border-radius: 6px;
  font-size: 15px;
}

.form-group input:focus {
  outline: none;
  border-color: #2196f3;
}

.form-actions {
  display: flex;
  flex-direction: column; /* 移动端按钮垂直排列 */
  gap: 12px;
  margin-top: 25px;
}

.btn-secondary,
.btn-primary {
  padding: 14px;
  border: none;
  border-radius: 6px;
  font-weight: 600;
  cursor: pointer;
}

.btn-secondary {
  background-color: transparent;
  color: #666;
  border: 2px solid #e0e0e0;
}

.btn-primary {
  background-color: #2196f3;
  color: white;
}

/* 平板端:双列布局 */
@media (min-width: 600px) {
  .responsive-form {
    padding: 30px;
  }

  .form-row {
    flex-direction: row; /* 水平排列 */
    gap: 20px;
  }

  .form-group {
    flex: 1; /* 平均分配空间 */
  }

  .form-group-full {
    flex: 1 1 100%; /* 占据整行 */
  }

  .form-actions {
    flex-direction: row; /* 水平排列按钮 */
    justify-content: flex-end;
    gap: 15px;
  }

  .btn-secondary,
  .btn-primary {
    flex: 0 0 auto; /* 不扩展 */
    min-width: 120px;
  }
}

/* 桌面端:优化间距 */
@media (min-width: 900px) {
  .responsive-form {
    padding: 40px;
  }

  .form-row {
    gap: 25px;
    margin-bottom: 25px;
  }
}

响应式圣杯布局

圣杯布局在不同屏幕尺寸下需要完全不同的排列方式。

html
<div class="layout">
  <header class="header">Header</header>

  <div class="content-wrapper">
    <nav class="sidebar-left">Left Sidebar</nav>
    <main class="main-content">Main Content</main>
    <aside class="sidebar-right">Right Sidebar</aside>
  </div>

  <footer class="footer">Footer</footer>
</div>
css
/* 移动端:完全垂直堆叠 */
.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header,
.footer {
  flex: 0 0 auto;
  padding: 20px;
  background-color: #2c3e50;
  color: white;
  text-align: center;
}

.content-wrapper {
  flex: 1; /* 占据剩余空间 */
  display: flex;
  flex-direction: column; /* 移动端垂直排列 */
}

.sidebar-left,
.sidebar-right,
.main-content {
  padding: 20px;
}

.sidebar-left {
  background-color: #ecf0f1;
  order: 1; /* 移动端:导航栏第一 */
}

.main-content {
  background-color: white;
  order: 2; /* 主内容第二 */
}

.sidebar-right {
  background-color: #f8f9fa;
  order: 3; /* 右侧边栏第三 */
}

/* 平板端:侧边栏堆叠,主内容全宽 */
@media (min-width: 768px) {
  .content-wrapper {
    flex-wrap: wrap; /* 允许换行 */
  }

  .sidebar-left,
  .sidebar-right {
    flex: 1 1 100%; /* 各占一行 */
  }

  .main-content {
    flex: 1 1 100%; /* 占据整行 */
    order: 1; /* 主内容优先 */
  }

  .sidebar-left {
    order: 2;
  }

  .sidebar-right {
    order: 3;
  }
}

/* 桌面端:经典三列布局 */
@media (min-width: 1024px) {
  .content-wrapper {
    flex-direction: row; /* 水平排列 */
    flex-wrap: nowrap; /* 不换行 */
  }

  .sidebar-left {
    flex: 0 0 220px; /* 固定宽度 */
    order: 1; /* 恢复左侧 */
  }

  .main-content {
    flex: 1; /* 占据剩余空间 */
    order: 2; /* 中间 */
  }

  .sidebar-right {
    flex: 0 0 220px; /* 固定宽度 */
    order: 3; /* 右侧 */
  }
}

/* 大屏幕:更宽的侧边栏 */
@media (min-width: 1400px) {
  .sidebar-left,
  .sidebar-right {
    flex-basis: 280px; /* 更宽的侧边栏 */
  }
}

这个布局会根据屏幕尺寸变化:

  • 移动端(<768px):完全垂直堆叠,导航栏在最上面
  • 平板端(768px-1023px):主内容全宽,两个侧边栏在下方堆叠
  • 桌面端(1024px+):经典三列布局
  • 大屏幕(1400px+):更宽的侧边栏

容器查询的未来

虽然媒体查询很强大,但它们基于视口尺寸,而不是容器尺寸。容器查询(Container Queries)是一个新特性,让元素可以根据其父容器的尺寸来响应。

css
/* 未来的容器查询语法 */
.card-container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}

@container (min-width: 600px) {
  .card {
    flex-direction: column;
  }
}

容器查询目前在现代浏览器中已经开始支持,但使用前要检查兼容性。

性能优化

响应式 Flexbox 布局的性能考虑:

避免过度使用媒体查询

css
/* 不好:太多媒体查询 */
@media (min-width: 320px) {
}
@media (min-width: 480px) {
}
@media (min-width: 600px) {
}
@media (min-width: 768px) {
}
@media (min-width: 992px) {
}
@media (min-width: 1200px) {
}

/* 更好:只在真正需要改变布局时设置断点 */
@media (min-width: 600px) {
} /* 平板 */
@media (min-width: 900px) {
} /* 桌面 */
@media (min-width: 1400px) {
} /* 大屏 */

使用 flex 简写

css
/* 不好:分开写影响性能 */
.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0%;
}

/* 更好:使用简写 */
.item {
  flex: 1;
}

减少重绘和重排

css
/* 避免在媒体查询中改变太多属性 */
@media (min-width: 768px) {
  .container {
    flex-direction: row; /* 只改变必要的属性 */
  }
}

实战案例:完整的响应式网站

让我们构建一个完整的响应式网站首页,综合运用所有学到的技术。

html
<div class="page">
  <!-- 导航栏 -->
  <nav class="navbar">
    <div class="logo">TechCorp</div>
    <ul class="nav-menu">
      <li><a href="#home">Home</a></li>
      <li><a href="#features">Features</a></li>
      <li><a href="#pricing">Pricing</a></li>
      <li><a href="#contact">Contact</a></li>
    </ul>
    <button class="btn-cta">Get Started</button>
  </nav>

  <!-- 英雄区域 -->
  <section class="hero">
    <div class="hero-content">
      <h1>Build Amazing Products</h1>
      <p>The modern platform for teams who want to ship faster</p>
      <div class="hero-actions">
        <button class="btn-primary">Start Free Trial</button>
        <button class="btn-secondary">Watch Demo</button>
      </div>
    </div>
    <div class="hero-image">
      <img src="hero.png" alt="Hero" />
    </div>
  </section>

  <!-- 特性网格 -->
  <section class="features">
    <h2>Why Choose Us</h2>
    <div class="feature-grid">
      <div class="feature-card">
        <div class="feature-icon">⚡</div>
        <h3>Lightning Fast</h3>
        <p>Optimized for speed and performance</p>
      </div>
      <div class="feature-card">
        <div class="feature-icon">🔒</div>
        <h3>Secure</h3>
        <p>Enterprise-grade security built-in</p>
      </div>
      <div class="feature-card">
        <div class="feature-icon">📈</div>
        <h3>Scalable</h3>
        <p>Grows with your business needs</p>
      </div>
      <div class="feature-card">
        <div class="feature-icon">💡</div>
        <h3>Innovative</h3>
        <p>Cutting-edge technology stack</p>
      </div>
    </div>
  </section>

  <!-- Footer -->
  <footer class="footer">
    <div class="footer-content">
      <div class="footer-column">
        <h4>Product</h4>
        <a href="#">Features</a>
        <a href="#">Pricing</a>
        <a href="#">Updates</a>
      </div>
      <div class="footer-column">
        <h4>Company</h4>
        <a href="#">About</a>
        <a href="#">Blog</a>
        <a href="#">Careers</a>
      </div>
      <div class="footer-column">
        <h4>Support</h4>
        <a href="#">Help Center</a>
        <a href="#">Contact</a>
        <a href="#">Status</a>
      </div>
    </div>
    <div class="footer-bottom">
      <p>&copy; 2025 TechCorp. All rights reserved.</p>
    </div>
  </footer>
</div>
css
/* 全局设置 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
}

/* 移动端优先布局 */

/* 导航栏 */
.navbar {
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 20px;
  background-color: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.logo {
  font-size: 24px;
  font-weight: bold;
  color: #2196f3;
}

.nav-menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
}

.nav-menu a {
  padding: 10px;
  color: #333;
  text-decoration: none;
}

.btn-cta {
  padding: 12px 24px;
  background-color: #2196f3;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

/* 英雄区域 */
.hero {
  display: flex;
  flex-direction: column;
  gap: 30px;
  padding: 40px 20px;
}

.hero-content h1 {
  font-size: 32px;
  margin-bottom: 15px;
  color: #333;
}

.hero-content p {
  font-size: 18px;
  color: #666;
  margin-bottom: 25px;
}

.hero-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.hero-image img {
  width: 100%;
  height: auto;
}

/* 特性区域 */
.features {
  padding: 60px 20px;
  background-color: #f5f5f5;
}

.features h2 {
  text-align: center;
  font-size: 32px;
  margin-bottom: 40px;
}

.feature-grid {
  display: flex;
  flex-direction: column;
  gap: 25px;
}

.feature-card {
  padding: 30px;
  background-color: white;
  border-radius: 12px;
  text-align: center;
}

.feature-icon {
  font-size: 48px;
  margin-bottom: 15px;
}

/* Footer */
.footer {
  padding: 40px 20px 20px;
  background-color: #2c3e50;
  color: white;
}

.footer-content {
  display: flex;
  flex-direction: column;
  gap: 30px;
  margin-bottom: 30px;
}

.footer-column {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer-column h4 {
  margin-bottom: 8px;
}

.footer-column a {
  color: #bbb;
  text-decoration: none;
}

.footer-bottom {
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  text-align: center;
  color: #999;
}

/* 平板端:600px+ */
@media (min-width: 600px) {
  .navbar {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .nav-menu {
    flex-direction: row;
    gap: 25px;
  }

  .hero-actions {
    flex-direction: row;
  }

  .feature-grid {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .feature-card {
    flex: 1 1 calc(50% - 12.5px); /* 2 列 */
  }

  .footer-content {
    flex-direction: row;
    justify-content: space-around;
  }
}

/* 桌面端:900px+ */
@media (min-width: 900px) {
  .hero {
    flex-direction: row;
    align-items: center;
    padding: 80px 60px;
    gap: 60px;
  }

  .hero-content {
    flex: 1;
  }

  .hero-image {
    flex: 1;
  }

  .hero-content h1 {
    font-size: 48px;
  }

  .hero-content p {
    font-size: 20px;
  }

  .feature-grid {
    flex-wrap: nowrap;
  }

  .feature-card {
    flex: 1 1 0; /* 4 列等宽 */
  }
}

/* 大屏幕:1200px+ */
@media (min-width: 1200px) {
  .navbar,
  .hero,
  .features {
    max-width: 1400px;
    margin: 0 auto;
  }

  .hero {
    padding: 100px 80px;
  }

  .features {
    padding: 80px;
  }
}

最佳实践总结

基于实际经验,响应式 Flexbox 的最佳实践:

1. 移动优先设计

css
/* ✅ 好的做法 */
.container {
  flex-direction: column;
}

@media (min-width: 768px) {
  .container {
    flex-direction: row;
  }
}

/* ❌ 避免 */
.container {
  flex-direction: row;
}

@media (max-width: 767px) {
  .container {
    flex-direction: column;
  }
}

2. 使用语义化的断点

css
/* ✅ 基于内容的断点 */
@media (min-width: 600px) {
} /* 卡片可以并排时 */
@media (min-width: 900px) {
} /* 导航可以水平排列时 */

/* ❌ 避免基于设备的断点 */
@media (min-width: 768px) {
} /* iPad 尺寸 */
@media (min-width: 1024px) {
} /* iPad Pro 尺寸 */

3. 合理使用 flex 值

css
/* 移动端:简单布局 */
.item {
  flex: 0 0 100%;
}

/* 桌面端:灵活布局 */
@media (min-width: 768px) {
  .item {
    flex: 1; /* 让 Flexbox 自动分配 */
  }
}

4. 测试各种尺寸

不要只测试常见断点,要测试断点之间的尺寸:

  • 移动端:320px, 375px, 414px
  • 平板端:768px, 834px, 1024px
  • 桌面端:1280px, 1440px, 1920px

5. 考虑触摸交互

在移动端,交互元素要足够大:

css
/* 移动端:更大的触摸目标 */
.btn {
  padding: 14px 20px;
  min-height: 44px; /* iOS 推荐的最小触摸目标 */
}

/* 桌面端:可以更小 */
@media (min-width: 768px) {
  .btn {
    padding: 10px 16px;
    min-height: auto;
  }
}

总结

响应式 Flexbox 是创建现代自适应布局的强大工具。关键要点:

核心策略:

  • 移动优先设计
  • 基于内容的断点
  • 渐进增强

常用模式:

  • 导航栏:垂直到水平的转换
  • 卡片网格:列数的动态调整
  • 表单:堆叠到并排的布局
  • 圣杯布局:完全重构的响应式设计

关键属性组合:

  • flex-direction + 媒体查询:改变排列方向
  • flex-wrap + 断点:控制换行行为
  • flex 值变化:调整空间分配
  • order:重排元素顺序

性能优化:

  • 减少媒体查询数量
  • 使用 flex 简写
  • 避免过度重排

掌握响应式 Flexbox 后,你就能创建真正适应各种设备的现代化布局。结合我们在前几章学到的 Flexbox 知识,你已经具备了使用 Flexbox 解决各种布局问题的能力。继续实践,在实际项目中应用这些技术,你会发现 Flexbox 是多么强大和灵活的布局工具。