Master CSS Container Queries in 12 Minutes with Copilot

Learn modern container query syntax for responsive components. Build cards that adapt to their parent, not the viewport.

Problem: Your Components Break in Tight Spaces

You built a card component that looks perfect at 1200px wide, but crams into a 300px sidebar and everything overlaps. Media queries can't help because they only see viewport size, not the card's actual container.

You'll learn:

  • How container queries work vs media queries
  • The @container syntax for responsive components
  • Using GitHub Copilot to generate container query code
  • Common pitfalls and how to avoid them

Time: 12 min | Level: Intermediate


Why This Happens

Media queries (@media) respond to viewport width. Your sidebar card sees the 1920px screen and tries to use desktop styles, even though it's squeezed into 300px of space.

Common symptoms:

  • Components look wrong in sidebars/grids
  • Same component needs different layouts in different contexts
  • Media query breakpoints don't match actual component needs
  • Copy-pasting styles for every container size

Example that fails:

/* This checks viewport, not the card's container */
@media (min-width: 768px) {
  .card { 
    display: grid;
    grid-template-columns: 200px 1fr; /* Breaks in narrow sidebars */
  }
}

Solution

Step 1: Set Up Container Context

First, tell the browser which element is the container to measure:

/* Define the container */
.sidebar,
.main-content,
.card-wrapper {
  container-type: inline-size; /* Measures width */
  container-name: card-container; /* Optional: name for targeting */
}

Why this works: container-type: inline-size makes the element a container context. Child elements can now query this container's width instead of the viewport.

If using Copilot: Type /* make this a container */ above your selector, then press Tab. Copilot suggests the container-type property.


Step 2: Write Container Queries

Now query the container, not the viewport:

/* Card adapts to its container */
.card {
  display: block; /* Mobile-first: stack by default */
}

/* When container is 400px+ wide, switch to grid */
@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 150px 1fr;
    gap: 1rem;
  }
}

/* When container is 600px+ wide, more space */
@container (min-width: 600px) {
  .card {
    grid-template-columns: 200px 1fr;
    gap: 1.5rem;
  }
}

Copilot tip: After writing @container, Copilot auto-suggests breakpoints based on your existing styles. Press Tab to accept, then customize the width values.


Step 3: Use Named Containers (Advanced)

When you have nested containers, target specific ones:

/* Define named containers */
.sidebar {
  container-name: sidebar;
  container-type: inline-size;
}

.main-content {
  container-name: main;
  container-type: inline-size;
}

/* Target specific container */
@container sidebar (min-width: 300px) {
  .card { padding: 0.5rem; }
}

@container main (min-width: 600px) {
  .card { padding: 2rem; }
}

Why this matters: Same .card component behaves differently in sidebar vs main area, even if both containers are the same width.

Copilot workflow:

  1. Type container-name: and Copilot suggests semantic names
  2. In @container, type the name and Copilot completes the query
  3. Copilot learns your naming patterns after 2-3 examples

Step 4: Combine with Container Query Units

Use cqw, cqh for sizes relative to the container:

@container (min-width: 400px) {
  .card-title {
    font-size: 5cqw; /* 5% of container width */
    max-font-size: 2rem; /* Cap it */
  }
  
  .card-image {
    height: 30cqh; /* 30% of container height */
  }
}

Container units:

  • cqw = 1% of container width
  • cqh = 1% of container height
  • cqi = 1% of container inline size (width in LTR)
  • cqb = 1% of container block size (height)

Copilot behavior: Type font-size: 5cq and Copilot suggests the unit. It knows container context from your @container rules.


Step 5: Full Example with Copilot

Let's build a real product card:

<div class="product-grid">
  <div class="product-card">
    <img src="product.jpg" alt="Product" class="product-image">
    <div class="product-info">
      <h3 class="product-title">Wireless Headphones</h3>
      <p class="product-price">$129.99</p>
      <button class="product-cta">Add to Cart</button>
    </div>
  </div>
</div>
/* Container setup */
.product-grid {
  container-type: inline-size;
  display: grid;
  gap: 1rem;
  /* Grid adapts with regular media queries */
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

/* Mobile-first card */
.product-card {
  background: white;
  border-radius: 8px;
  overflow: hidden;
}

.product-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.product-info {
  padding: 1rem;
}

/* Container query: when card has space */
@container (min-width: 350px) {
  .product-card {
    display: grid;
    grid-template-columns: 40% 1fr; /* Side-by-side */
  }
  
  .product-image {
    height: 100%; /* Fill container height */
  }
  
  .product-cta {
    width: auto; /* Shrink button */
    padding: 0.5rem 1.5rem;
  }
}

/* Container query: wide cards get more breathing room */
@container (min-width: 500px) {
  .product-info {
    padding: 2rem;
  }
  
  .product-title {
    font-size: 4cqw; /* Scales with container */
    max-font-size: 1.5rem;
  }
}

How Copilot helps here:

  1. After typing .product-card {, Copilot suggests display properties
  2. Type @container and it suggests breakpoints from your container setup
  3. For font-size:, Copilot offers both cqw and rem - pick what fits
  4. It learns your spacing scale (1rem, 1.5rem, 2rem) and suggests consistently

If it fails:

  • Container queries not working: Check browser support (Chrome 105+, Safari 16+, Firefox 110+)
  • Styles not applying: Ensure parent has container-type set
  • Nested containers broken: Add container-name to target the right one
  • Copilot suggesting media queries: Comment /* use container query */ to guide it

Verification

Test it:

  1. Open browser DevTools
  2. Resize the container element (not the window)
  3. Watch styles change at container breakpoints

You should see: Card layout switches when the container hits 350px, regardless of viewport size.

DevTools tip (Chrome 105+):

  • Open Elements panel → Styles
  • Look for "Container Queries" section
  • Shows active container and matching queries

Container Queries vs Media Queries

Use @container when:

  • Component lives in multiple contexts (sidebar, main, grid)
  • Layout depends on parent size, not screen size
  • Building reusable components for design systems

Use @media when:

  • Changing page-level layout (header, navigation)
  • Adapting to device capabilities (touch, hover)
  • Overall page structure that always matches viewport

Use both:

/* Page layout uses media queries */
@media (min-width: 1024px) {
  .layout {
    display: grid;
    grid-template-columns: 300px 1fr; /* Sidebar + main */
  }
}

/* Components inside use container queries */
@container (min-width: 400px) {
  .card { /* Adapts to its space */ }
}

What You Learned

  • Container queries measure the parent container, not viewport
  • container-type: inline-size enables container queries
  • @container syntax mirrors @media but checks container width
  • Container units (cqw, cqh) size elements relative to containers
  • GitHub Copilot learns your container patterns and suggests matching queries

Limitations:

  • Browser support: Chrome 105+, Safari 16+, Firefox 110+ (IE/old browsers need fallbacks)
  • Can't query container's own properties (only descendants can query it)
  • container-type creates a new containing block (affects absolute positioning)

Copilot Productivity Tips

Train Copilot on your patterns:

  1. Write 2-3 container queries manually with your preferred breakpoints
  2. Copilot learns your values (e.g., 400px, 600px, 800px)
  3. Future suggestions match your spacing scale

Use comments to guide:

/* small container layout */
@container (min-width: 300px) { /* Copilot fills this */ }

/* medium container, grid layout */
@container (min-width: 500px) { /* Copilot suggests grid */ }

Accept and modify:

  • Copilot often suggests min-width: 768px (common media query breakpoint)
  • Accept it, then change to your container's actual breakpoint
  • Copilot adapts to your edits over time

Keyboard shortcuts:

  • Tab = Accept suggestion
  • Alt + ] = Next suggestion (if Copilot offers alternatives)
  • Esc = Dismiss suggestion

Tested on Chrome 121, Safari 17.2, Firefox 122, with GitHub Copilot v1.156+

Browser compatibility: All modern browsers as of 2026. For legacy support, see CSS Container Query Polyfill.