DEV Community

Cover image for CSS Container Queries Tutorial for Beginners
Akash for MechCloud Academy

Posted on

CSS Container Queries Tutorial for Beginners

CSS container queries are a powerful feature that allows you to style elements based on the size of their parent container, rather than the entire viewport. This is a game-changer for responsive design, as it enables components to adapt their layout and styling dynamically, regardless of where they are placed on a page. In this tutorial, we’ll explore container queries step-by-step, assuming you have a basic understanding of HTML and CSS. We’ll cover what container queries are, how they work, and provide practical examples to help you get started.

What Are Container Queries?

Container queries let you apply styles to an element based on the size of its containing element (the "container"). Unlike media queries, which rely on the viewport’s dimensions (e.g., the browser window’s width or height), container queries focus on the size of a specific parent element. This makes them ideal for designing reusable components, such as cards, widgets, or modules, that need to adapt their appearance based on the space they occupy.

For example, imagine a card component that changes its layout from a stacked to a side-by-side arrangement when its container is wide enough. With container queries, you can define these style changes without worrying about the viewport size or the card’s position on the page.

Container queries were introduced to address limitations in responsive design, particularly for modular and component-based web development. They are supported in all modern browsers (Chrome, Edge, Firefox, Safari) as of 2025, making them a reliable tool for web developers.

Why Use Container Queries?

Before diving into the syntax, let’s understand why container queries are useful:

  • Component Flexibility: Components can adapt their styles based on their container’s size, making them reusable in different contexts (e.g., sidebars, main content, or grids).
  • Improved Maintainability: You can define styles locally within a component, reducing reliance on global viewport-based rules.
  • Dynamic Layouts: Container queries enable layouts that respond to the available space, enhancing user experience on diverse devices and screen sizes.

How Do Container Queries Work?

To use container queries, you need to:

  1. Define a Container: Specify which element acts as the container using the container-type property.
  2. Query the Container: Use the @container rule to apply styles based on the container’s size or other properties.
  3. Style the Contained Elements: Target child elements within the container to apply conditional styles.

Key Properties and Syntax

  • container-type: Defines an element as a container and specifies what properties can be queried. Common values are:
    • size: Allows querying the container’s width, height, or aspect ratio.
    • inline-size: Focuses on the container’s inline axis (usually width in horizontal writing modes).
    • block-size: Focuses on the container’s block axis (usually height).
  • container-name: Optionally assigns a name to the container for specific targeting.
  • @container: The at-rule used to write container queries, similar to @media for media queries.

Here’s a basic syntax example:

/* Define a container */
.parent {
  container-type: inline-size;
  container-name: card-container;
}

/* Apply styles based on container size */
@container card-container (min-width: 300px) {
  .child {
    background-color: lightblue;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the .child element gets a light blue background when the .parent container is at least 300px wide.

Step-by-Step Example: Building a Responsive Card Component

Let’s create a practical example to demonstrate container queries. We’ll build a card component that changes its layout based on the width of its container. The card will display an image and text stacked vertically in narrow containers and side-by-side in wider containers.

Step 1: Set Up the HTML

Create a simple HTML structure with a container and a card component:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Container Queries Demo</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="container">
    <div class="card">
      <img src="https://via.placeholder.com/150" alt="Sample image">
      <div class="card-content">
        <h2>Card Title</h2>
        <p>This is a sample card description. It adapts based on the container size!</p>
      </div>
    </div>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 2: Define the Container and Basic Styles

In your styles.css, define the container and style the card for its default (narrow) state:

/* Set up the container */
.container {
  container-type: inline-size; /* Query the inline size (width) */
  container-name: card-container;
  width: 100%;
  max-width: 600px; /* Simulate different container sizes */
  margin: 20px auto;
  padding: 10px;
  border: 1px solid #ccc;
}

/* Default card styles (stacked layout) */
.card {
  display: flex;
  flex-direction: column;
  background-color: #f9f9f9;
  border-radius: 8px;
  overflow: hidden;
}

.card img {
  width: 100%;
  height: auto;
}

.card-content {
  padding: 15px;
}

.card-content h2 {
  margin: 0 0 10px;
  font-size: 1.5rem;
}

.card-content p {
  margin: 0;
  font-size: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Here, we’ve:

  • Made the .container a container with container-type: inline-size and named it card-container.
  • Styled the .card to stack the image and content vertically by default.
  • Added basic styling for the image and text.

Step 3: Add Container Queries

Now, let’s use a container query to switch to a side-by-side layout when the container is at least 400px wide:

/* Container query for wider containers */
@container card-container (min-width: 400px) {
  .card {
    flex-direction: row;
    align-items: center;
  }

  .card img {
    width: 50%; /* Image takes half the width */
    height: auto;
  }

  .card-content {
    width: 50%; /* Content takes half the width */
    padding: 20px;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this query:

  • When the container’s width is 400px or more, the .card switches to flex-direction: row, placing the image and content side-by-side.
  • The image and content each take 50% of the card’s width, and we adjust padding for better spacing.

Step 4: Test the Responsive Behavior

To see the container query in action, you can:

  • Resize the browser window if the container’s width is set to 100% or a percentage.
  • Adjust the max-width of the .container in your CSS to simulate different container sizes (e.g., change max-width: 600px to max-width: 300px to test the stacked layout).

You can also create multiple containers with different widths to test the card’s adaptability:

<div class="container" style="max-width: 300px;">
  <div class="card">
    <img src="https://via.placeholder.com/150" alt="Sample image">
    <div class="card-content">
      <h2>Small Card</h2>
      <p>This card is in a narrow container.</p>
    </div>
  </div>
</div>

<div class="container" style="max-width: 500px;">
  <div class="card">
    <img src="https://via.placeholder.com/150" alt="Sample image">
    <div class="card-content">
      <h2>Wide Card</h2>
      <p>This card is in a wider container.</p>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Both cards will adapt their layout based on their respective container’s width, demonstrating the power of container queries.

Advanced Example: Multiple Breakpoints

Let’s extend the card example to include multiple breakpoints for more nuanced styling:

/* Default styles (narrow containers) */
.card {
  display: flex;
  flex-direction: column;
  background-color: #f9f9f9;
  border-radius: 8px;
  overflow: hidden;
  font-size: 0.9rem;
}

/* Medium containers (300px and up) */
@container card-container (min-width: 300px) {
  .card {
    font-size: 1rem;
  }
  .card-content {
    padding: 15px;
  }
}

/* Wide containers (400px and up) */
@container card-container (min-width: 400px) {
  .card {
    flex-direction: row;
    align-items: center;
  }
  .card img {
    width: 50%;
  }
  .card-content {
    width: 50%;
    padding: 20px;
  }
}

/* Very wide containers (500px and up) */
@container card-container (min-width: 500px) {
  .card {
    font-size: 1.1rem;
  }
  .card-content h2 {
    font-size: 1.8rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we’ve added:

  • A breakpoint at 300px to slightly increase font size and padding.
  • The existing 400px breakpoint for the side-by-side layout.
  • A 500px breakpoint to further increase font sizes for better readability in larger containers.

This approach allows fine-grained control over the card’s appearance as the container size changes.

Browser Support and Fallbacks

As of 2025, container queries are supported in all major browsers (Chrome 105+, Firefox 110+, Safari 16+, Edge 105+). However, for older browsers, you should provide fallbacks:

  • Default Styles: Ensure the default styles (outside any @container rule) are functional and visually acceptable.
  • Feature Detection: Use @supports to check for container query support:
/* Fallback for browsers without container query support */
.card {
  flex-direction: column;
}

/* Container query for supported browsers */
@supports (container-type: inline-size) {
  .container {
    container-type: inline-size;
    container-name: card-container;
  }

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

This ensures that browsers without container query support still render a usable layout.

Tips for Using Container Queries

  • Use inline-size for Most Cases: Since most responsive designs focus on width, container-type: inline-size is often sufficient.
  • Name Containers for Clarity: Assign meaningful container-name values to avoid confusion when working with multiple containers.
  • Combine with Media Queries: Container queries handle component-level responsiveness, but media queries are still useful for viewport-level adjustments.
  • Test Across Sizes: Test your components in various container sizes to ensure smooth transitions and proper styling.

Conclusion

CSS container queries empower developers to create flexible, reusable components that adapt to their container’s size, revolutionizing responsive design. By defining containers with container-type and using @container rules, you can craft layouts that respond dynamically to their context. In this tutorial, we explored the basics of container queries, built a responsive card component, and added multiple breakpoints for refined control. With practice, you’ll find container queries to be an essential tool for modern web development.

Try experimenting with different container sizes, components, and queries to deepen your understanding. Happy coding!

Top comments (0)