|
1 | | -<ComingSoon /> |
| 1 | +--- |
| 2 | +title: "CSS Container Queries" |
| 3 | +description: "Learn how to use CSS Container Queries to style components based on the size of their parent container, enabling true component-level responsiveness." |
| 4 | +keywords: [CSS Container Queries, '@container', container-type, container-name, component responsiveness, local scoping] |
| 5 | +tags: [css, responsiveness, container-queries, '@container', component-design, local-scoping, modern-css, container-type, container-name] |
| 6 | +sidebar_label: "Container Queries" |
| 7 | +--- |
| 8 | + |
| 9 | +Container Queries are a modern, powerful feature in CSS that allows you to apply styles to an element based on the dimensions (size or style) of its nearest ancestor with containment set, rather than the global viewport size. |
| 10 | + |
| 11 | +This is a paradigm shift in responsive design, moving from a page-centric approach to a **component-centric** approach. |
| 12 | + |
| 13 | +<AdsComponent /> |
| 14 | +<br /> |
| 15 | + |
| 16 | +## 1. The Problem Solved |
| 17 | + |
| 18 | +### Media Queries vs. Container Queries |
| 19 | + |
| 20 | +Historically, we relied on **Media Queries** (`@media`). |
| 21 | + |
| 22 | + * **Media Queries:** Apply styles based on the size of the **viewport** (the browser window). If a small card component is placed in a narrow sidebar on a large screen, a media query for a large screen would make the card look bad because it only checks the global size. |
| 23 | + |
| 24 | +**Container Queries** (`@container`) solve this: |
| 25 | + |
| 26 | + * **Container Queries:** Apply styles based on the size of the **parent element** (the container). The card component can now adjust its layout (e.g., stack its elements) when its container is narrow, regardless of whether the user is on a mobile phone or a large desktop monitor. |
| 27 | + |
| 28 | +## 2. Setting Up the Container |
| 29 | + |
| 30 | +Before you can query a container, you must establish it using the `container` or `container-type` property on the parent element. |
| 31 | + |
| 32 | +### 2.1. `container-type` (Required) |
| 33 | + |
| 34 | +This property defines what kind of dimension is being queried. |
| 35 | + |
| 36 | +| Value | Description | Use Case | |
| 37 | +| :--- | :--- | :--- | |
| 38 | +| **`size`** | Queries both the **width and height**. | Rarely used, as it can cause infinite layout loops. | |
| 39 | +| **`inline-size`** | Queries the size in the direction of text flow (usually **width**). | Most common and safest choice for block elements. | |
| 40 | +| **`normal`** | The default, no containment established. | | |
| 41 | + |
| 42 | +### 2.2. `container-name` (Optional but Recommended) |
| 43 | + |
| 44 | +For clarity and to prevent ambiguity when containers are nested, you can give your container a name. |
| 45 | + |
| 46 | +<AdsComponent /> |
| 47 | +<br /> |
| 48 | + |
| 49 | +### Setup Shorthand |
| 50 | + |
| 51 | +The `container` shorthand combines both properties: |
| 52 | + |
| 53 | +```css title="styles.css" |
| 54 | +/* Applied to the PARENT element */ |
| 55 | +.sidebar-module { |
| 56 | + /* Establishes containment and gives it a name for targeting */ |
| 57 | + container: card-container / inline-size; |
| 58 | + /* Equivalent to: |
| 59 | + container-name: card-container; |
| 60 | + container-type: inline-size; */ |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +## 3. The `@container` Rule |
| 65 | + |
| 66 | +Once the parent is defined, you can use the `@container` rule on its children to apply responsive styles. |
| 67 | + |
| 68 | +### 3.1. Syntax |
| 69 | + |
| 70 | +The syntax is similar to a media query, but it uses the container's size instead of the viewport's size. |
| 71 | + |
| 72 | +```css title="styles.css" |
| 73 | +@container [container-name] ([query-feature]) { |
| 74 | + /* Styles for the child element */ |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +In the example above: |
| 79 | +* **Container Name** (optional) specifies which container to query. If omitted, it queries the nearest ancestor with containment. |
| 80 | +* **Query Feature** is the condition based on the container's dimensions (e.g., `min-width: 400px`). |
| 81 | + |
| 82 | +### 3.2. Query Features |
| 83 | + |
| 84 | +The features are size-based and mirror those used in media queries: |
| 85 | + |
| 86 | + * `min-width` / `max-width` (based on container width) |
| 87 | + * `min-height` / `max-height` (based on container height) |
| 88 | + * `min-inline-size` / `max-inline-size` (most common) |
| 89 | + |
| 90 | +### Example: Component Responsiveness |
| 91 | + |
| 92 | +```css title="styles.css" |
| 93 | +/* Styles applied to a child element inside .sidebar-module */ |
| 94 | +.card-content { |
| 95 | + display: flex; /* Default horizontal layout */ |
| 96 | + gap: 1rem; |
| 97 | +} |
| 98 | + |
| 99 | +/* Query the parent named 'card-container' */ |
| 100 | +@container card-container (max-width: 400px) { |
| 101 | + .card-content { |
| 102 | + /* When the parent container is narrow, stack the children */ |
| 103 | + flex-direction: column; |
| 104 | + gap: 0.5rem; |
| 105 | + } |
| 106 | + |
| 107 | + .card-content img { |
| 108 | + /* Shrink the image when the container is small */ |
| 109 | + width: 100%; |
| 110 | + height: auto; |
| 111 | + } |
| 112 | +} |
| 113 | +``` |
| 114 | + |
| 115 | +<AdsComponent /> |
| 116 | +<br /> |
| 117 | + |
| 118 | +## 4. Logical Operators |
| 119 | + |
| 120 | +Like media queries, you can combine queries using `and`, `not`, and the comma for `or`. |
| 121 | + |
| 122 | +```css title="styles.css" |
| 123 | +@container (min-width: 300px) and (max-width: 500px) { |
| 124 | + /* Styles apply only if the container width is between 300px and 500px */ |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +## Interactive Container Query Demo |
| 129 | + |
| 130 | +Observe how the internal structure of the `Card` component changes when you resize the outer container, regardless of the overall viewport size. |
| 131 | + |
| 132 | +<CodePenEmbed |
| 133 | + title="Interactive Container Query Demo" |
| 134 | + penId="emZKepL" |
| 135 | +/> |
0 commit comments