Skip to main content
Featured Article

Container Queries v2: Dynamic Multi-Axis Layouts Revolution 🚀

Master CSS Container Queries v2 with multi-axis queries, style(), state(), and discrete queries for truly dynamic components that adapt to size, style, and state—no JavaScript required.

  • 2 MIN
  • Pankaj Kumar
Updated: coding

Share

  • Whatsapp Icon
  • Twitter Icon
  • Telegram Icon
  • Linkedin Icon
  • Facebook Icon
Container Queries v2: Dynamic Multi-Axis Layouts Revolution 🚀
coding 2 min read

Master CSS Container Queries v2 with multi-axis queries, style(), state(), and discrete queries for truly dynamic components that adapt to size, style, and state—no JavaScript required.

Container Queries v2: Dynamic Multi-Axis Layouts 🚀

  • Container Queries v2 ships full cross-browser support in 2026, introducing @container style(), @container state(), multi-axis queries, and cqi/cqb/cqh units that make components respond to size + style + state simultaneously ⚙️.
  • Forget viewport-based media queries—v2 enables truly modular components that adapt their layout, typography, and behavior based on their actual container context, regardless of screen size đź’ˇ.
  • This production guide covers enterprise-grade patterns for cards, dashboards, pricing tables, and complex grids that automatically reflow across any layout.

🎯 Container Queries v2 Superpowers

v1 (2024)v2 (2026)
@container (min-width: 400px)@container (width > 400px AND height > 300px)
Size onlySize + Style + State
cqi unitscqi/cqb/cqh + style() + state()
Single-axisMulti-axis queries

🏗️ Complete Multi-Axis Dashboard Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Container Queries v2: Multi-Axis Dashboard</title>
  <style>
    /* SYSTEM RESET */
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, sans-serif;
      background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
      min-height: 100vh;
      padding: 2rem;
    }

    /* DASHBOARD CONTAINER */
    .dashboard {
      container-type: size style;  /* v2: Track size AND style */
      max-width: 1400px;
      margin: 0 auto;
      background: rgba(255, 255, 255, 0.05);
      backdrop-filter: blur(20px);
      border-radius: 24px;
      padding: 2rem;
      border: 1px solid rgba(255, 255, 255, 0.1);
    }

    /* RESPONSIVE GRID SYSTEM */
    .stats-grid {
      display: grid;
      gap: 1.5rem;
      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    }

    /* v2 STAT CARDS - Multi-axis responsive */
    .stat-card {
      background: rgba(255, 255, 255, 0.1);
      backdrop-filter: blur(20px);
      border-radius: 20px;
      padding: 2rem;
      border: 1px solid rgba(255, 255, 255, 0.2);
      color: white;
      
      /* Default: Compact mobile layout */
      display: flex;
      flex-direction: column;
      gap: 1rem;
      font-size: 0.9rem;
    }

    .stat-number {
      font-size: 2.5rem;
      font-weight: 800;
      line-height: 1;
    }

    .stat-label {
      opacity: 0.9;
      font-weight: 500;
    }

    /* v2: SIZE + MULTI-AXIS QUERIES */
    @container (min-width: 350px) and (min-height: 200px) {
      .stat-card {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        padding: 1.5rem;
        font-size: 1rem;
      }
      
      .stat-number {
        font-size: clamp(2rem, 6cqi, 3.5rem);  /* Container-relative! */
      }
    }

    /* v2: RESPONSIVE TYPOGRAPHY WITH cqi */
    @container (min-width: 450px) and (aspect-ratio > 1.2) {
      .stat-card {
        padding: 2.5rem;
      }
      
      .stat-number {
        font-size: clamp(3rem, 8cqi, 4.5rem);
      }
      
      .stat-label {
        font-size: 1.1rem;
      }
    }

    /* v2: STYLE QUERIES - Detect container styling */
    @container style(--layout: grid) {
      .stats-grid {
        grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
      }
      
      .stat-card {
        border-radius: 16px;
        box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
      }
    }

    /* v2: STATE QUERIES - Detect container state */
    @container state(--theme: dark) {
      .stat-card {
        background: rgba(0, 0, 0, 0.3);
        border-color: rgba(255, 255, 255, 0.4);
      }
    }

    /* PRICING TABLE EXAMPLE */
    .pricing-section {
      container-type: size style;
      max-width: 1200px;
      margin: 4rem auto;
      padding: 3rem;
      display: grid;
      gap: 2rem;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    }

    .pricing-card {
      background: rgba(255, 255, 255, 0.1);
      border-radius: 24px;
      padding: 3rem 2rem;
      text-align: center;
      position: relative;
      border: 1px solid rgba(255, 255, 255, 0.2);
      
      /* Default stacked layout */
      gap: 1.5rem;
    }

    .price-header {
      font-size: 1.5rem;
      font-weight: 700;
    }

    .price-amount {
      font-size: 3rem;
      font-weight: 900;
      background: linear-gradient(135deg, #fff 0%, #e0e7ff 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }

    /* v2: Multi-axis pricing card */
    @container (min-width: 400px) and (min-height: 450px) {
      .pricing-card {
        display: flex;
        flex-direction: column;
        height: 100%;
      }
      
      .price-features {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        margin-top: auto;
      }
    }

    /* v2: Feature list becomes columns */
    @container (min-width: 500px) and (aspect-ratio > 1.5) {
      .price-features {
        column-count: 2;
        column-gap: 2rem;
      }
      
      .price-amount {
        font-size: clamp(4rem, 10cqi, 6rem);
      }
    }

    /* CONTROLS FOR DEMO */
    .controls {
      position: fixed;
      top: 20px;
      right: 20px;
      display: flex;
      gap: 1rem;
      z-index: 1000;
    }

    .control-btn {
      padding: 12px 20px;
      border: none;
      border-radius: 12px;
      background: rgba(255, 255, 255, 0.2);
      color: white;
      font-weight: 600;
      cursor: pointer;
      backdrop-filter: blur(10px);
      transition: all 0.2s ease;
    }

    .control-btn:hover {
      background: rgba(255, 255, 255, 0.3);
      transform: translateY(-2px);
    }
  </style>
</head>
<body>
  <!-- Demo Controls -->
  <div class="controls">
    <button class="control-btn" onclick="toggleLayout()">Grid/List</button>
    <button class="control-btn" onclick="toggleTheme()">Dark/Light</button>
    <button class="control-btn" onclick="resizeDashboard()">Resize</button>
  </div>

  <!-- MAIN DASHBOARD -->
  <div class="dashboard" id="dashboard" style="--layout: flex;">
    <h1 style="color: white; text-align: center; font-size: clamp(2rem, 5vw, 3.5rem); margin-bottom: 3rem;">
      Container Queries v2 Dashboard ✨
    </h1>
    
    <div class="stats-grid">
      <div class="stat-card">
        <div class="stat-number" data-value="12,456">12,456</div>
        <div class="stat-label">Active Users</div>
      </div>
      <div class="stat-card">
        <div class="stat-number" data-value="2.3M">$2.3M</div>
        <div class="stat-label">Revenue</div>
      </div>
      <div class="stat-card">
        <div class="stat-number" data-value="98.7%">98.7%</div>
        <div class="stat-label">Uptime</div>
      </div>
      <div class="stat-card">
        <div class="stat-number" data-value="847">847</div>
        <div class="stat-label">Transactions</div>
      </div>
    </div>
  </div>

  <!-- PRICING SECTION -->
  <section class="pricing-section">
    <div class="pricing-card">
      <div class="price-header">Starter</div>
      <div class="price-amount">$29<small>/mo</small></div>
      <ul class="price-features">
        <li>âś“ 5 Projects</li>
        <li>âś“ 10 Team Members</li>
        <li>âś“ Basic Analytics</li>
        <li>âś“ Email Support</li>
      </ul>
    </div>
    
    <div class="pricing-card">
      <div class="price-header">Pro</div>
      <div class="price-amount">$99<small>/mo</small></div>
      <ul class="price-features">
        <li>âś“ 50 Projects</li>
        <li>âś“ Unlimited Members</li>
        <li>âś“ Advanced Analytics</li>
        <li>âś“ Priority Support</li>
        <li>âś“ API Access</li>
      </ul>
    </div>
    
    <div class="pricing-card">
      <div class="price-header">Enterprise</div>
      <div class="price-amount">$299<small>/mo</small></div>
      <ul class="price-features">
        <li>âś“ Unlimited Everything</li>
        <li>âś“ Custom Integrations</li>
        <li>âś“ 24/7 Support</li>
        <li>âś“ Dedicated Manager</li>
        <li>âś“ On-Prem Option</li>
      </ul>
    </div>
  </section>

  <script>
    function toggleLayout() {
      const dash = document.getElementById('dashboard');
      dash.style.setProperty('--layout', dash.style.getPropertyValue('--layout') === 'flex' ? 'grid' : 'flex');
    }
    
    function toggleTheme() {
      document.documentElement.toggleAttribute('data-theme', 'dark');
    }
    
    function resizeDashboard() {
      const dash = document.getElementById('dashboard');
      dash.style.width = dash.style.width === '800px' ? '1400px' : '800px';
    }
  </script>
</body>
</html>

đź”§ v2 Syntax Deep Dive

1. Multi-Axis Queries

@container (min-width: 400px) and (min-height: 300px) {
  /* Only triggers when BOTH conditions met */
}

2. Container Style Queries

/* Container sets custom property */
.dashboard {
  container-type: style;
  --layout: grid;
}

/* Component responds to container style */
@container style(--layout: grid) {
  .card { border-radius: 16px; }
}

3. Container State Queries

@container state(--loading: true) {
  .card { opacity: 0.5; }
}

4. Container Query Units (cqi/cqb/cqh)

.font-size: clamp(1.5rem, 4cqi, 3rem);  /* 4% of container inline size */
.height: 20cqh;                         /* 20% of container height */

⚖️ Media Queries vs Container Queries v2

ScenarioMedia Query ❌Container Query v2 ✅
Card in SidebarWrong layoutAdapts to 300px width
Dashboard WidgetViewport-basedContainer-based
Pricing TableMobile-first hellMulti-axis perfect
Reusable ComponentsContext-blindContext-aware
Dynamic GridsJS requiredPure CSS

🎯 Production Checklist

âś… container-type: size style (track both)
âś… Multi-axis: width AND height queries
âś… cqi/cqb/cqh units for fluid typography
âś… @container style() for theme detection
âś… @container state() for loading/error states
âś… Combine with grid/flex for layouts
âś… @supports fallbacks for older browsers

🔥 Real-World Use Cases

  1. Dashboard Widgets - Reflow 1→2→3 columns automatically
  2. Pricing Cards - Stack→Row→Multi-column based on space
  3. Product Cards - Image left/right based on container width
  4. Navigation - Hamburger→Tabs→Full menu by container size
  5. Modals - Compact→Expanded based on modal width
  • Container Queries v2 = End of viewport-based responsive hell.
  • Components now adapt to their actual context, not screen size. Copy, paste, ship 🚀.

Explore Related Topics

Stay Updated with Our Latest Articles

Subscribe to our newsletter and get exclusive content, tips, and insights delivered directly to your inbox.

We respect your privacy. Unsubscribe at any time.

About the Author

pankaj kumar - Author

pankaj kumar

Blogger

pankaj.syal1@gmail.com