CSS container queries have landed and are now available for experimentation. Let’s look at what problem is being solved, learn how container queries work, and see how they compare with and complement existing CSS features for layout.
Container Query Discussion:
CSS containment provides a way to isolate parts of a page and declare to the browser these parts are independent of the rest of the page in terms of styles and layout. If you are creating a responsive design, you often use media queries to change the page layout based on the size of the viewport. It’s common to group HTML elements into reusable components that have a specific layout depending on the available space on a page. The available space might be not only depending on the size of the viewport, but also on the context where a component appears.Container queries allow us to look at a container size and apply styles to the contents based on the size of their container rather than the viewport or other device characteristics. If the container has less space in the surrounding context, you can hide certain elements or use smaller fonts, for example. The illustration below shows how the same card component can be displayed with multiple layouts using container queries:CSS Container Queries — A Revolution for responsive web design
There’s no other feature that web designers have asked for more than being able to style elements based on the size of their parent. There were many attempts to solve this problem by attaching resize event on the element or using ResizeObvserver. Luckily, thanks to smart people like Miriam Suzanne, there’s excellent progress on the native implementation of CSS Container Queries defined as part of the CSS Containment Module Specification.Do You still need media queries? Yes!
The container-type property creates a containment context. The inline-size creates a query container that reacts to changes on the inline axis (width). We can also use block-size to be able to adjust styling based on the element’s block axis (height), size to react to changes on both axis, style to react to style changes, and state to react to state queries. The container-name allows us to add a descriptive name to a container.The new @container rule allows us to style elements based on the size of the containment context. A lot like @media query, but better!Syntax:
The syntax of container queries is similar to that of media queries.Container query comes with three extra properties and a rule.- Container-type: Defines an element as a query container. It allows child components to query aspects of its sizing, layout, style, and, state against it.
- Size: Establishes a query container for dimensional queries on the block and inline axis. Applies layout, style, and size containment to the element.
- Inline-size: Establishes a query container for dimensional queries on the inline axis of the container. Applies layout, style, and inline-size containment to the element.
- Normal: The element is not a query container for any dimensional queries on the block and inline axis.
- Container-name: Sets a name to the query container for filtering.
- Container: A shorthand property to set both container-type and container-name.
JSX:
<aside>
<div class="main-wrapper">
<div class="aboutme">
...
</div>
</div>
</aside>
<main>
<div class="main-wrapper">
<div class="aboutme">
...
</div>
</div>
</main>
CSS:
/* Default style */
.main-wrapper {
container-type: inline-size;
}
.avatar {
width: 4rem;
height: 4rem;
}
.aboutme header {
display: flex;
align-items: center;
gap: 1rem;
}
h1 {
font-size: 23px;
}
/* Large style */
@container (min-width: 800px) {
.aboutme {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 10rem;
height: 10rem;
}
header {
display: block;
}
h1 {
font-size: 46px;
}
}
We wrap the div with the class name aboutme present in aside and main by a container with the class main-wrapper and remove the large class from the main area.With the following CSS, the browser knows we might want to query this container later.It creates a container with containment on the inline axis only. The content can grow to as large as it needs to be on the block axis. .main-wrapper {
container-type: inline-size;
}
A container query is created using @container. This will query the nearest containment context.
The below code shows the larger Profile component when the main content is wider than 800px.@container (min-width: 800px) {
....;
}
Awesome! This is what we wanted. We can use this same component in different places and it will behave as per the parent component width.