引言

五年前我在开发电商首页时,曾对着十几种不同尺寸的设备调试布局到凌晨三点。当屏幕尺寸小到某个临界值时,原本优雅的图片画廊突然变得像被挤扁的巧克力盒子。这就是传统响应式设计的痛点:我们总在和整个视窗较劲,却忽视了组件自身的自适应能力。好在现在有了容器查询,它与媒体查询的组合让响应式设计进入了新纪元。


一、媒体查询:响应式设计的"老将"依然闪耀

1.1 基础使用姿势

媒体查询就像网页的自动变色眼镜,通过@media规则感知视窗变化。这是最经典的移动优先布局写法:

/* 技术栈:纯CSS */
/* 基础移动端样式 */
.container {
  padding: 1rem;
}

/* 平板及以上设备 */
@media (min-width: 768px) {
  .container {
    max-width: 720px;
    display: grid;  /* 启用网格布局 */
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 桌面端大屏幕 */
@media (min-width: 1200px) {
  .container {
    max-width: 1140px;
    grid-template-columns: repeat(3, 1fr);  /* 三列布局 */
  }
}

这个示例展示了经典的「三段式」断点设计,就像搭积木一样在不同视窗尺寸下重建布局结构。

1.2 常被忽略的媒体特性

除了视窗宽度,我们还可以监控更多设备特性:

/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
  body { background: #333; color: white; }
}

/* 打印样式优化 */
@media print {
  nav, footer { display: none; }  /* 隐藏无关元素 */
  .content { columns: 1; }  /* 取消分栏 */
}

二、容器查询:让组件学会"自力更生"

2.1 突破视窗限制的新维度

容器查询的关键在于赋予组件独立判断能力。假设我们要开发一个自适应卡片组件:

<!-- 技术栈:纯CSS容器查询 -->
<style>
  .card-container {
    container-type: inline-size; /* 声明为容器 */
    container-name: cardArea;
  }

  .card {
    padding: 1rem;
    background: #f5f5f5;
  }

  /* 容器宽度≥400px时的样式 */
  @container cardArea (min-width: 400px) {
    .card {
      display: flex;  /* 启用弹性盒子 */
      gap: 1.5rem;
    }
    
    .card img {
      width: 120px;  /* 固定图片宽度 */
    }
  }
</style>

<div class="card-container">
  <article class="card">
    <img src="product.jpg">
    <div class="content">...</div>
  </article>
</div>

这个卡片在窄容器中呈现堆叠布局,当父容器足够宽时自动切换为并排布局——这一切不依赖视窗尺寸,仅取决于父容器的可用空间。

2.2 组合技:容器查询+媒体查询

在实际项目中,两者可以组合使用:

/* 大屏幕下启用容器查询 */
@media (min-width: 1024px) {
  .dashboard {
    container-type: inline-size;
  }
  
  @container (min-width: 800px) {
    .widget {
      grid-template-columns: 1fr 2fr;  
    }
  }
}

三、实战:新闻站点布局的完全体方案

3.1 宏观布局用媒体查询

/* 全局布局控制 */
.main-layout {
  display: grid;
  grid-template-areas: "header" "content" "sidebar" "footer";
}

@media (min-width: 768px) {
  .main-layout {
    grid-template-columns: 1fr 300px;  /* 边栏固定宽度 */
    grid-template-areas: 
      "header header"
      "content sidebar"
      "footer footer";
  }
}

3.2 组件级适配用容器查询

.article-card {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .article-card {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);  /* 宽容器显示阴影 */
  }
  
  .article-meta {
    display: flex;
    justify-content: space-between;  /* 并排显示元信息 */
  }
}

四、技术选型指南

4.1 使用场景对照表

场景 媒体查询 容器查询
全局布局调整
组件内部布局变化
设备特性适配
第三方组件封装

(✓推荐使用 △可用但非最佳 ✗不适用)

4.2 优缺点全景图

媒体查询优势:

  • 浏览器支持率100%
  • 适合调整全局布局
  • 可检测设备物理特性

容器查询闪光点:

  • 组件级响应式控制
  • 不依赖全局视窗尺寸
  • 提升代码可维护性

五、避坑备忘录

  1. 容器查询的"相对单位"陷阱 容器查询内的百分比单位基于容器尺寸,不是视窗宽度

  2. 移动端慎用resize监听

    // 错误示范:频繁触发重排
    window.addEventListener('resize', updateLayout);
    
    // 正确姿势:节流处理 + 被动监听
    window.addEventListener('resize', throttle(updateLayout), { passive: true });
    
  3. 渐进增强策略

    /* 基础布局保证可用性 */
    .component {
      min-width: 240px;
    }
    
    /* 容器查询作为增强体验 */
    @supports (container-type: inline-size) {
      .component {
        container-type: inline-size;
      }
    }
    

六、未来展望

谷歌最新提出的scope提案正在尝试统一两种查询方式。想象这样的未来写法:

@scope (.dashboard) {
  @media (width >= 800px) {
    /* 同时响应容器和视窗变化 */
  }
}

七、文章总结

把媒体查询比作城市规划师,负责宏观的城市(页面)布局;容器查询则是建筑师,专注每栋建筑(组件)的自我调节。二者不是取代关系,而是现代响应式设计的"黄金搭档"。

理解何时使用全局控制(媒体查询),何时需要组件自治(容器查询),是打造完美自适应体验的关键。记住:好的响应式设计应该像水一样,既能顺应环境(媒体查询),又能保持个体特性(容器查询)。