写这么多年CSS,都不知道什么是容器查询?

一、基础概念与 API 详解

1.1 什么是容器查询

容器查询(Container Queries)是 CSS 的一个革命性功能,它允许元素根据其父容器的尺寸来应用不同的样式,而不是根据视口(viewport)的尺寸。这为响应式设计带来了全新的可能性。

1.2 核心 API 概述

Container Type 属性

css 复制代码
/* 定义容器类型 */
.container {
  container-type: size; /* 查询容器的宽度和高度 */
  container-type: inline-size; /* 只查询容器的内联尺寸(宽度) */
  container-type: normal; /* 不建立查询容器 */
}

Container Name 属性

css 复制代码
/* 为容器命名 */
.sidebar {
  container-name: sidebar;
  container-type: inline-size;
}
​
/* 简写形式 */
.main-content {
  container: main / inline-size;
}

@container 规则

css 复制代码
/* 基础语法 */
@container (min-width: 300px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}
​
/* 命名容器查询 */
@container sidebar (max-width: 200px) {
  .nav-item {
    flex-direction: column;
  }
}

1.3 元素查询概念

元素查询(Element Queries)是一个扩展概念,指的是基于单个元素自身的特性来应用样式,包括容器查询在内的各种查询技术。

二、浏览器兼容性

2.1 当前支持状态

浏览器 版本 支持状态
Chrome 105+ ✅ 完全支持
Firefox 110+ ✅ 完全支持
Safari 16.0+ ✅ 完全支持
Edge 105+ ✅ 完全支持

2.2 渐进式增强策略

css 复制代码
/* 基础样式(所有浏览器) */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
​
.card {
  flex: 1 1 300px;
  background: white;
  border-radius: 8px;
  padding: 1rem;
}
​
/* 容器查询增强(支持的浏览器) */
@supports (container-type: inline-size) {
  .card-container {
    container-type: inline-size;
  }
​
  @container (min-width: 400px) {
    .card {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 1rem;
    }
  }
}

2.3 Polyfill 解决方案

html 复制代码
<!-- 引入 container-query-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/container-query-polyfill@^1/dist/container-query-polyfill.modern.js"></script>

三、实战演示

3.1 响应式卡片组件

效果展示

  • 卡片会根据其容器的宽度自动调整布局
  • 小容器:垂直堆叠布局
  • 中等容器:水平并排布局
  • 大容器:网格布局

3.2 侧边栏自适应导航

效果展示

  • 宽侧边栏:显示图标和文字
  • 窄侧边栏:只显示图标
  • 超窄侧边栏:折叠为汉堡菜单

3.3 动态表格布局

效果展示

  • 大容器:完整的表格视图
  • 中等容器:卡片式布局
  • 小容器:列表式布局

四、完整实战示例

html 复制代码
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>CSS容器查询与元素查询</title>
    <style>
      /* 全局样式重置 */
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
​
      body {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          sans-serif;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        min-height: 100vh;
        padding: 2rem;
      }
​
      .container {
        max-width: 1400px;
        margin: 0 auto;
      }
​
      .page-header {
        text-align: center;
        color: white;
        margin-bottom: 3rem;
      }
​
      .page-title {
        font-size: 2.5rem;
        font-weight: 700;
        margin-bottom: 0.5rem;
        text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
      }
​
      .page-subtitle {
        font-size: 1.125rem;
        opacity: 0.9;
      }
​
      /* 演示区域样式 */
      .demo-section {
        background: white;
        border-radius: 16px;
        padding: 2rem;
        margin-bottom: 2rem;
        box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
      }
​
      .section-title {
        font-size: 1.5rem;
        font-weight: 600;
        color: #1a202c;
        margin-bottom: 1rem;
        border-bottom: 2px solid #667eea;
        padding-bottom: 0.5rem;
        display: inline-block;
      }
​
      .section-description {
        color: #6b7280;
        margin-bottom: 1.5rem;
        line-height: 1.6;
      }
​
      /* 演示1:响应式卡片组件 */
      .card-demo {
        display: grid;
        gap: 2rem;
        grid-template-columns: 1fr 2fr;
      }
​
      .resize-controls {
        background: #f8fafc;
        border-radius: 8px;
        padding: 1rem;
      }
​
      .control-group {
        margin-bottom: 1rem;
      }
​
      .control-label {
        display: block;
        font-size: 0.875rem;
        font-weight: 500;
        color: #374151;
        margin-bottom: 0.5rem;
      }
​
      .control-slider {
        width: 100%;
        height: 4px;
        border-radius: 2px;
        background: #e5e7eb;
        outline: none;
        cursor: pointer;
      }
​
      .control-value {
        display: inline-block;
        background: #667eea;
        color: white;
        padding: 0.25rem 0.5rem;
        border-radius: 4px;
        font-size: 0.75rem;
        font-weight: 500;
        margin-top: 0.5rem;
      }
​
      .card-container {
        container-type: inline-size;
        border: 2px dashed #d1d5db;
        border-radius: 8px;
        padding: 1rem;
        resize: horizontal;
        overflow: auto;
        min-width: 200px;
        max-width: 100%;
        width: 400px;
      }
​
      .product-card {
        background: white;
        border-radius: 12px;
        overflow: hidden;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        transition: all 0.3s ease;
      }
​
      .product-card:hover {
        transform: translateY(-4px);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
      }
​
      /* 小容器样式 (< 300px) */
      .card-image {
        width: 100%;
        height: 200px;
        object-fit: cover;
        background: linear-gradient(45deg, #667eea, #764ba2);
      }
​
      .card-content {
        padding: 1rem;
      }
​
      .card-title {
        font-size: 1.125rem;
        font-weight: 600;
        color: #1a202c;
        margin-bottom: 0.5rem;
      }
​
      .card-description {
        color: #6b7280;
        font-size: 0.875rem;
        margin-bottom: 1rem;
        line-height: 1.5;
      }
​
      .card-price {
        font-size: 1.25rem;
        font-weight: 700;
        color: #667eea;
        margin-bottom: 1rem;
      }
​
      .card-button {
        width: 100%;
        background: #667eea;
        color: white;
        border: none;
        padding: 0.75rem;
        border-radius: 6px;
        font-weight: 500;
        cursor: pointer;
        transition: background 0.3s ease;
      }
​
      .card-button:hover {
        background: #5a67d8;
      }
​
      /* 中等容器样式 (300px - 500px) */
      @container (min-width: 300px) {
        .product-card {
          display: grid;
          grid-template-columns: 120px 1fr;
          align-items: start;
        }
​
        .card-image {
          height: 120px;
          margin: 1rem 0 1rem 1rem;
          border-radius: 8px;
        }
​
        .card-content {
          padding: 1rem 1rem 1rem 0;
        }
​
        .card-button {
          width: auto;
          padding: 0.5rem 1rem;
        }
      }
​
      /* 大容器样式 (> 500px) */
      @container (min-width: 500px) {
        .product-card {
          grid-template-columns: 150px 1fr auto;
          grid-template-rows: auto;
          gap: 1rem;
          align-items: center;
        }
​
        .card-image {
          height: 100px;
          margin: 1rem;
        }
​
        .card-content {
          padding: 1rem 0;
        }
​
        .card-actions {
          padding: 1rem;
          display: flex;
          flex-direction: column;
          gap: 0.5rem;
        }
​
        .card-button {
          white-space: nowrap;
        }
​
        .card-wishlist {
          background: transparent;
          color: #6b7280;
          border: 1px solid #d1d5db;
          padding: 0.5rem 1rem;
          border-radius: 6px;
          cursor: pointer;
          transition: all 0.3s ease;
        }
​
        .card-wishlist:hover {
          color: #ef4444;
          border-color: #ef4444;
        }
      }
​
      /* 演示2:侧边栏导航 */
      .sidebar-demo {
        display: grid;
        grid-template-columns: auto 1fr;
        gap: 2rem;
        min-height: 400px;
      }
​
      .sidebar-container {
        container-type: inline-size;
        width: 250px;
        resize: horizontal;
        overflow: auto;
        min-width: 60px;
        max-width: 400px;
      }
​
      .sidebar {
        background: #1f2937;
        height: 400px;
        border-radius: 8px;
        padding: 1rem;
        overflow: hidden;
      }
​
      .nav-item {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.75rem;
        color: #d1d5db;
        text-decoration: none;
        border-radius: 6px;
        margin-bottom: 0.5rem;
        transition: all 0.3s ease;
        white-space: nowrap;
      }
​
      .nav-item:hover {
        background: #374151;
        color: white;
      }
​
      .nav-icon {
        font-size: 1.25rem;
        flex-shrink: 0;
      }
​
      .nav-text {
        font-weight: 500;
      }
​
      /* 窄侧边栏样式 (< 120px) */
      @container (max-width: 120px) {
        .nav-text {
          display: none;
        }
​
        .nav-item {
          justify-content: center;
          padding: 0.75rem 0.5rem;
        }
      }
​
      /* 超窄侧边栏样式 (< 80px) */
      @container (max-width: 80px) {
        .sidebar {
          padding: 0.5rem;
        }
​
        .nav-item {
          padding: 0.5rem;
          margin-bottom: 0.25rem;
        }
​
        .nav-icon {
          font-size: 1rem;
        }
      }
​
      .sidebar-content {
        background: #f8fafc;
        border-radius: 8px;
        padding: 2rem;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #6b7280;
        font-style: italic;
      }
​
      /* 演示3:数据表格 */
      .table-container {
        container-type: inline-size;
        border: 2px dashed #d1d5db;
        border-radius: 8px;
        padding: 1rem;
        resize: horizontal;
        overflow: auto;
        min-width: 300px;
        max-width: 100%;
        width: 600px;
        margin-top: 1rem;
      }
​
      .data-table {
        width: 100%;
        background: white;
        border-radius: 8px;
        overflow: hidden;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      }
​
      .table-row {
        display: grid;
        grid-template-columns: 1fr 100px 100px 80px;
        gap: 1rem;
        padding: 1rem;
        border-bottom: 1px solid #e5e7eb;
        align-items: center;
      }
​
      .table-row:last-child {
        border-bottom: none;
      }
​
      .table-row:nth-child(even) {
        background: #f9fafb;
      }
​
      .table-header {
        background: #667eea !important;
        color: white;
        font-weight: 600;
      }
​
      .employee-name {
        font-weight: 500;
        color: #1f2937;
      }
​
      .employee-role {
        color: #6b7280;
        font-size: 0.875rem;
      }
​
      .status-badge {
        padding: 0.25rem 0.5rem;
        border-radius: 9999px;
        font-size: 0.75rem;
        font-weight: 500;
        text-align: center;
      }
​
      .status-active {
        background: #dcfce7;
        color: #166534;
      }
​
      .status-inactive {
        background: #fee2e2;
        color: #991b1b;
      }
​
      .action-button {
        background: transparent;
        border: 1px solid #d1d5db;
        color: #6b7280;
        padding: 0.25rem 0.5rem;
        border-radius: 4px;
        cursor: pointer;
        font-size: 0.75rem;
        transition: all 0.3s ease;
      }
​
      .action-button:hover {
        background: #667eea;
        color: white;
        border-color: #667eea;
      }
​
      /* 中等容器样式 (400px - 600px) */
      @container (max-width: 600px) {
        .table-row {
          grid-template-columns: 1fr 80px;
          gap: 0.5rem;
        }
​
        .employee-role,
        .status-badge {
          grid-column: 1;
          margin-top: 0.5rem;
        }
​
        .action-button {
          grid-column: 2;
          grid-row: 1 / span 2;
          align-self: center;
        }
      }
​
      /* 小容器样式 (< 400px) */
      @container (max-width: 400px) {
        .table-row {
          grid-template-columns: 1fr;
          gap: 0.5rem;
          padding: 1.5rem 1rem;
        }
​
        .table-header {
          display: none;
        }
​
        .employee-name::before {
          content: '姓名: ';
          font-weight: normal;
          color: #6b7280;
        }
​
        .employee-role::before {
          content: '职位: ';
          font-weight: normal;
        }
​
        .status-badge::before {
          content: '状态: ';
          color: #6b7280;
          font-weight: normal;
        }
      }
​
      /* 响应式设计 */
      @media (max-width: 768px) {
        .card-demo,
        .sidebar-demo {
          grid-template-columns: 1fr;
        }
​
        .container {
          padding: 1rem;
        }
​
        .page-title {
          font-size: 2rem;
        }
      }
​
      /* 性能优化 */
      .product-card,
      .nav-item,
      .table-row {
        will-change: transform;
      }
​
      /* 辅助工具类 */
      .text-center {
        text-align: center;
      }
      .mb-2 {
        margin-bottom: 0.5rem;
      }
      .mb-4 {
        margin-bottom: 1rem;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <!-- 页面头部 -->
      <header class="page-header">
        <h1 class="page-title">CSS容器查询与元素查询</h1>
        <p class="page-subtitle">响应式设计的新纪元 - 基于容器的智能布局</p>
      </header>
​
      <!-- 演示1:响应式卡片组件 -->
      <section class="demo-section">
        <h2 class="section-title">演示1:响应式产品卡片</h2>
        <p class="section-description">
          拖拽容器边缘调整宽度,观察卡片如何根据容器大小自动调整布局。
        </p>
​
        <div class="card-demo">
          <div class="resize-controls">
            <div class="control-group">
              <label class="control-label">容器宽度</label>
              <input
                type="range"
                class="control-slider"
                id="cardWidth"
                min="200"
                max="800"
                value="400"
              />
              <span class="control-value" id="cardWidthValue">400px</span>
            </div>
            <div class="control-group">
              <h4 style="margin-bottom: 0.5rem; color: #374151;">布局变化:</h4>
              <div
                style="font-size: 0.875rem; color: #6b7280; line-height: 1.5;"
              >
                • <strong>< 300px:</strong> 垂直堆叠布局<br />
                • <strong>300-500px:</strong> 水平并排布局<br />
                • <strong>> 500px:</strong> 三列网格布局
              </div>
            </div>
          </div>
​
          <div class="card-container" id="cardContainer">
            <div class="product-card">
              <div class="card-image"></div>
              <div class="card-content">
                <h3 class="card-title">智能手表 Pro</h3>
                <p class="card-description">
                  全新设计的智能手表,具备健康监测、运动跟踪等多项功能。
                </p>
                <div class="card-price">¥2,999</div>
                <button class="card-button">立即购买</button>
              </div>
              <div class="card-actions">
                <button class="card-wishlist">❤ 收藏</button>
              </div>
            </div>
          </div>
        </div>
      </section>
​
      <!-- 演示2:侧边栏导航 -->
      <section class="demo-section">
        <h2 class="section-title">演示2:自适应侧边栏导航</h2>
        <p class="section-description">
          拖拽侧边栏边缘调整宽度,观察导航项如何自动适应空间变化。
        </p>
​
        <div class="sidebar-demo">
          <div class="sidebar-container">
            <nav class="sidebar">
              <a href="#" class="nav-item">
                <span class="nav-icon">🏠</span>
                <span class="nav-text">首页</span>
              </a>
              <a href="#" class="nav-item">
                <span class="nav-icon">📊</span>
                <span class="nav-text">数据分析</span>
              </a>
              <a href="#" class="nav-item">
                <span class="nav-icon">👥</span>
                <span class="nav-text">用户管理</span>
              </a>
              <a href="#" class="nav-item">
                <span class="nav-icon">⚙️</span>
                <span class="nav-text">系统设置</span>
              </a>
              <a href="#" class="nav-item">
                <span class="nav-icon">📝</span>
                <span class="nav-text">内容管理</span>
              </a>
              <a href="#" class="nav-item">
                <span class="nav-icon">📈</span>
                <span class="nav-text">统计报表</span>
              </a>
            </nav>
          </div>
​
          <div class="sidebar-content">
            <div>
              <h3 style="color: #1f2937; margin-bottom: 0.5rem;">
                主要内容区域
              </h3>
              <p>这里是主要内容区域,会根据侧边栏的变化自动调整。</p>
            </div>
          </div>
        </div>
      </section>
​
      <!-- 演示3:动态表格布局 -->
      <section class="demo-section">
        <h2 class="section-title">演示3:响应式数据表格</h2>
        <p class="section-description">
          拖拽表格容器边缘,观察表格如何从完整视图转换为卡片式和列表式布局。
        </p>
​
        <div class="table-container">
          <div class="data-table">
            <div class="table-row table-header">
              <div>员工姓名</div>
              <div>职位</div>
              <div>状态</div>
              <div>操作</div>
            </div>
            <div class="table-row">
              <div class="employee-name">张三</div>
              <div class="employee-role">前端工程师</div>
              <div class="status-badge status-active">在职</div>
              <button class="action-button">编辑</button>
            </div>
            <div class="table-row">
              <div class="employee-name">李四</div>
              <div class="employee-role">UI设计师</div>
              <div class="status-badge status-active">在职</div>
              <button class="action-button">编辑</button>
            </div>
            <div class="table-row">
              <div class="employee-name">王五</div>
              <div class="employee-role">产品经理</div>
              <div class="status-badge status-inactive">离职</div>
              <button class="action-button">查看</button>
            </div>
            <div class="table-row">
              <div class="employee-name">赵六</div>
              <div class="employee-role">后端工程师</div>
              <div class="status-badge status-active">在职</div>
              <button class="action-button">编辑</button>
            </div>
          </div>
        </div>
      </section>
    </div>
​
    <script>
      // 卡片容器宽度控制
      const cardWidthSlider = document.getElementById('cardWidth');
      const cardWidthValue = document.getElementById('cardWidthValue');
      const cardContainer = document.getElementById('cardContainer');
​
      cardWidthSlider.addEventListener('input', function () {
        const width = this.value + 'px';
        cardContainer.style.width = width;
        cardWidthValue.textContent = width;
      });
​
      // 检测容器查询支持
      function checkContainerQuerySupport() {
        if (CSS.supports('container-type', 'inline-size')) {
          console.log('✅ 浏览器支持容器查询');
          return true;
        } else {
          console.log('❌ 浏览器不支持容器查询');
          // 可以在这里添加 polyfill 或降级处理
          return false;
        }
      }
​
      // 动态添加容器查询示例
      function addDynamicContainerQuery() {
        const style = document.createElement('style');
        style.textContent = `
        @container (min-width: 350px) and (max-width: 450px) {
          .product-card {
            border: 3px solid #10b981;
          }
          
          .card-title::after {
            content: " 🎯";
          }
        }
      `;
        document.head.appendChild(style);
      }
​
      // 监听容器尺寸变化
      function observeContainerSize() {
        if (window.ResizeObserver) {
          const observer = new ResizeObserver((entries) => {
            entries.forEach((entry) => {
              const width = entry.contentRect.width;
              console.log(`容器宽度变化: ${width}px`);
​
              // 根据容器大小添加不同的 CSS 类
              const container = entry.target;
              container.classList.remove('small', 'medium', 'large');
​
              if (width < 300) {
                container.classList.add('small');
              } else if (width < 500) {
                container.classList.add('medium');
              } else {
                container.classList.add('large');
              }
            });
          });
​
          observer.observe(cardContainer);
        }
      }
​
      // 添加交互反馈
      function addInteractiveFeedback() {
        // 卡片按钮点击效果
        document.querySelectorAll('.card-button').forEach((button) => {
          button.addEventListener('click', function () {
            const originalText = this.textContent;
            this.textContent = '已添加到购物车!';
            this.style.background = '#10b981';
​
            setTimeout(() => {
              this.textContent = originalText;
              this.style.background = '';
            }, 2000);
          });
        });
​
        // 导航项点击效果
        document.querySelectorAll('.nav-item').forEach((item) => {
          item.addEventListener('click', function (e) {
            e.preventDefault();
​
            // 移除其他项的活跃状态
            document.querySelectorAll('.nav-item').forEach((nav) => {
              nav.style.background = '';
            });
​
            // 添加当前项的活跃状态
            this.style.background = '#667eea';
          });
        });
​
        // 表格操作按钮
        document.querySelectorAll('.action-button').forEach((button) => {
          button.addEventListener('click', function () {
            const row = this.closest('.table-row');
            row.style.background = '#fef3cd';
​
            setTimeout(() => {
              row.style.background = '';
            }, 1000);
          });
        });
      }
​
      // 性能监控
      function monitorPerformance() {
        if ('PerformanceObserver' in window) {
          const observer = new PerformanceObserver((list) => {
            const entries = list.getEntries();
            entries.forEach((entry) => {
              if (entry.entryType === 'measure') {
                console.log(`性能测量: ${entry.name} - ${entry.duration}ms`);
              }
            });
          });
​
          observer.observe({ entryTypes: ['measure'] });
        }
      }
​
      // 初始化
      document.addEventListener('DOMContentLoaded', function () {
        // 检查浏览器支持
        const supportsContainerQueries = checkContainerQuerySupport();
​
        if (supportsContainerQueries) {
          // 添加动态容器查询
          addDynamicContainerQuery();
​
          // 监听容器尺寸变化
          observeContainerSize();
        } else {
          // 显示降级提示
          const notice = document.createElement('div');
          notice.style.cssText = `
          background: #fef3cd;
          border: 1px solid #f59e0b;
          color: #92400e;
          padding: 1rem;
          border-radius: 8px;
          margin-bottom: 2rem;
          text-align: center;
        `;
          notice.textContent =
            '您的浏览器不支持容器查询,部分效果可能无法正常显示。建议升级到最新版本的 Chrome、Firefox 或 Safari。';
​
          document
            .querySelector('.container')
            .insertBefore(notice, document.querySelector('.demo-section'));
        }
​
        // 添加交互反馈
        addInteractiveFeedback();
​
        // 性能监控
        monitorPerformance();
​
        // 记录页面加载完成
        performance.mark('page-loaded');
      });
​
      // 添加键盘快捷键
      document.addEventListener('keydown', function (e) {
        // Alt + 1, 2, 3 快速调整卡片容器大小
        if (e.altKey) {
          switch (e.key) {
            case '1':
              cardWidthSlider.value = 250;
              cardWidthSlider.dispatchEvent(new Event('input'));
              break;
            case '2':
              cardWidthSlider.value = 400;
              cardWidthSlider.dispatchEvent(new Event('input'));
              break;
            case '3':
              cardWidthSlider.value = 600;
              cardWidthSlider.dispatchEvent(new Event('input'));
              break;
          }
        }
      });
​
      // 导出调试信息
      window.containerQueryDebug = {
        getContainerInfo: function (selector) {
          const element = document.querySelector(selector);
          if (!element) return null;
​
          const computedStyle = getComputedStyle(element);
          return {
            containerType: computedStyle.containerType,
            containerName: computedStyle.containerName,
            width: element.offsetWidth,
            height: element.offsetHeight,
          };
        },
​
        listAllContainers: function () {
          const containers = document.querySelectorAll(
            '[style*="container-type"], .card-container, .sidebar-container, .table-container'
          );
          return Array.from(containers).map((container) => ({
            element: container,
            info: this.getContainerInfo(
              '.' + container.className.split(' ')[0]
            ),
          }));
        },
      };
    </script>
  </body>
</html>

五、实战技巧与最佳实践

5.1 命名策略

css 复制代码
/* 使用语义化的容器名称 */
.sidebar {
  container: sidebar-nav / inline-size;
}
​
.main-content {
  container: content-area / size;
}
​
.card-grid {
  container: card-container / inline-size;
}

5.2 性能优化

css 复制代码
/* 只在需要时启用容器查询 */
.component {
  container-type: normal; /* 默认值 */
}
​
.component--responsive {
  container-type: inline-size; /* 只在响应式组件上启用 */
}

5.3 调试技巧

css 复制代码
/* 添加视觉调试边框 */
@container (min-width: 300px) {
  .debug-mode .card {
    outline: 2px solid red;
  }
}

六、与传统媒体查询的对比

6.1 媒体查询的局限性

css 复制代码
/* 传统媒体查询 - 基于视口 */
@media (max-width: 768px) {
  .card {
    flex-direction: column;
  }
}

6.2 容器查询的优势

css 复制代码
/* 容器查询 - 基于容器 */
@container (max-width: 300px) {
  .card {
    flex-direction: column;
  }
}

七、未来展望

容器查询为 CSS 带来了真正的组件化响应式设计能力,让我们能够创建更加灵活和可维护的界面组件。随着浏览器支持的完善,它将成为现代前端开发的标准工具。

7.1 即将到来的功能

  • 样式查询(Style Queries)
  • 状态查询(State Queries)
  • 更多查询条件支持

7.2 最佳实践建议

  1. 渐进式增强:始终提供基础样式,容器查询作为增强
  2. 性能考虑:避免过度嵌套的容器查询
  3. 语义化命名:使用清晰的容器名称
  4. 调试工具:利用开发者工具监控容器状态
  5. 团队协作:建立容器查询的编码规范

通过掌握容器查询,我们能够构建真正响应容器大小的组件,实现更精确和灵活的响应式设计。

相关推荐
摸着石头过河的石头3 小时前
函数的超能力:JavaScript高阶函数完全指南
前端·javascript
曦曜2923 小时前
聊聊前端静态页面的开发
css·html
进击的二向箔3 小时前
Vue 3 深度解析:Composition API 如何改变前端开发方式
前端
golang学习记3 小时前
从0死磕全栈之Next.js 表单开发终极指南:使用 Server Actions 构建高效、安全、现代化的表单
前端
纯爱掌门人3 小时前
我把前端踩坑经验总结成28条“涨薪秘籍”,老板夸同事赞,新手照着做准没错
前端·程序员·代码规范
LuckySusu3 小时前
【vue篇】Vue 模板编译全解析:从 Template 到 DOM 的奇妙旅程
前端·vue.js
LuckySusu3 小时前
【vue篇】Vue 响应式更新揭秘:数据变了,DOM 为何不立即刷新?
前端·vue.js
LuckySusu3 小时前
【vue篇】Vue 事件修饰符完全指南:精准控制事件流
前端·vue.js
6269603 小时前
前端页面出现问题ResizeObserver loop completed with undelivered notifications.
前端