@container - CSS At-rule

@container

Summary of characteristics of the @container at-rule

Quick description
Allows you to write conditional CSS rules based on the characteristics of the container.
Status
Standard
W3C Module
CSS Containment Module
Document status: WD (Working Draft)

Description of the @container at-rule.

The directive @container introduces the ability to write conditional styles based on an element's dimensions.
The right term is container query.

@media directive) allow you to adjust styles based on the device's features: viewport size, screen orientation, etc., container queries look at the characteristics of a page element (the container) to decide whether or not to apply styles to its child elements.

Note: a container queries request can only apply styles to the children of the element that was declared as the container. The container itself cannot be styled in a container queries request that concerns it.

Demonstration of a container query In this first example, the Firefox logo is a floating image on the left, which allows the description to be next to the image.
But if the container's width is too small, the lines of text next to the image will be very short, making reading difficult.
The container's width can be limited by the layout: for example, this container could be in a grid cell containing other elements, and the column widths are dynamic.
For the purposes of the demonstration, we made the container's width adjustable with the mouse.
Démonstration of a container query In this second example, a container query was used to make the image non-floating when the container's width is too small (less than 200 pixels).
As above, you can adjust the container's width with the mouse to simulate a layout constraint.

Syntax elements:

For any overflow, you need to define which element is the container and what type of container it is. This can be done with the properties container-name and container-type, or more simply with the shorthand property container .
For the example above, we defined that the container's name is demo and that it works along the row axis. The image is also set to float to the left by default.

#description1b { container-name: demo; container-type: inline-size; } #description1b img { float:left; margin-right:10px; }

Note: the container ID can be set on a class, so not necessarily for a single element.

Next, you need to write the actual container query. This can only refer to child elements of the container. Here, we declare that the image is no longer floating if the container's width is less than 200 pixels.

@container demo (width < 200px) { #description1b img { float:none; margin-right:200px; } }

Other examples.

We know that justified text doesn't look very good on short lines: it causes ridiculously big spaces between words. A container query was used to align the text to the left when the container's width is less than 300 pixels.

Here, the writing direction adjusts based on the shape of the container: if it's wider than it is tall, the writing is horizontal, and vertical if it's taller than it is wide.

Units specific to container queries.

Several units have been created to express dimensions based on the dimensions of the container element. See CSS units relating to the container.

Advantages of container queries.

The main advantage of container queries is that they allow you to style an element independently of the rest of the page. This is especially useful for components, which can be inserted into a page whose layout is unknown.

The requests like scroll-state.

These queries let you find out about the scrolling state of the container: can it still scroll in one direction or another? Is it a container with snapping (scrolling with snaps)? And finally, for containers in sticky position, is the container stuck at one end of the screen, and if so, which one?

The style container queries requests.

This evolution of container queries allows testing any property of the container element. It's the computed value of the property that is taken into account.
But this feature is still not widely supported.

Syntaxes of the @container at-rule.

The very simple examples given here consist of a container element that serves for containment, and an internal element on which the properties are adjusted. It is indeed not possible to change the properties of the container itself.

  • @container id (width > 200px) and (width < 400px) { ... }

    This is the basic syntax of a container query.

    • id is an optional identifier. It will have been set by the property container-name or container on one or more elements of the page.
      If it is not provided, the query applies to all containers on the page.
    • (width > 200px) is a condition involving a property and a value. It's the computed value of the property that is considered.
    • and, or or not are operators that allow you to combine multiple conditions, with each condition being written inside parentheses.

    The properties that can be used in conditions are:

    • width and height: width or height of the container element.
    • inline-size and block-size:size of the container element in the inline direction, or in the block direction.
    • aspect-ratio: ratio corresponding to the width of the container element divided by its height.
    • orientation: takes the value landscape if the width of the container element is greater than its height, and the value portrait otherwise.

    Tests on height (height), block direction size (block-size), ratio, and orientation are only supported on containers of type size (see container-type ).

    This text turns red as soon as the width is less than 150 pixels.
    This text turns red as soon as its orientation is in portrait. We wrote not(orientation:landscape), which comes to the same thing. Change its dimensions to see for yourself.
    This text turns red as soon as its width is less than its height. Change its dimensions to see it happen.

    Browsers basically recognize another syntax, inherited from the past, which is less readable than the previous one. Here is this old syntax, along with the equivalents.
    @container id ((min-width: 200px) and (max-width: 400px)) { sélecteur { propriétés CSS } }
    min-width: value
    width > value
    max-width: value
    width < value
    min-height: value
    height > value
    max-height: value
    height < value
  • @container id scroll-state(stuck:top) { ... }

    The stuck descriptor is only active on elements whose position property is sticky. Used with the scroll-state() function, it activates when the container element is "stuck" by one of its edges:

    • none: the stuck element doesn't play any role.
    • top: the element is stuck to the top edge.
    • right: the element is stuck to the right edge.
    • bottom: the element is stuck to the bottom edge.
    • left: the element is stuck to the left edge.
    • block-start: the element is stuck to the edge corresponding to the start of the blocks.
    • block-end: the element is stuck to the edge corresponding to the end of the blocks.
    • inline-start: the element is stuck to the edge corresponding to the start of the lines.
    • inline-end: the element is stuck to the edge corresponding to the end of the lines.

    The type of container (container-type) must be scroll-state.

    The example below is made up of a container block (id=stuck-container), which contains a text element (id=stuck-element). The container block is position:sticky, it receives the properties container-type, set to scroll-state, and an ID defined by container-name. The element turns red when sticky:bottom.
    Scroll the page up to stick the block to the bottom of the screen.

    This doesn't work on all browsers.

    This text turns red as soon as it's pasted by its lower edge.
  • @container id scroll-state(scrollable: top) { ... }

    The scrollable descriptor is triggered when the container can be scrolled (presence of a scrollbar and content exceeding the container's size).

    • none: the scrollable element doesn't play any role.
    • top : the element can be scrolled up.
    • right : the element can be scrolled to the right.
    • bottom : the element can be scrolled to the bottom.
    • left : the element can be scrolled to the left.
    • x : the element can be scrolled horizontally.
    • y : the element can be scrolled vertically.
    • block-start : the element is stuck to the edge corresponding to the start of the blocks.
    • block-end : the element is stuck to the edge corresponding to the end of the blocks.
    • inline-start : the element is stuck to the edge corresponding to the start of the lines.
    • inline-end : the element is stuck to the edge corresponding to the end of the lines.
    • block : the element can be scrolled in the direction of the blocks.
    • inline : the element can be scrolled in the direction of the lines.

    Here too, the type of container must be scroll-state.

    The main element is the containment container (id=scroll-container). It contains an element (id=scroll-element) with text long enough to require scrolling. Two container query requests display the element in blue when scrolling up is no longer possible, and in red when scrolling down is no longer possible. Keep in mind that these queries can only affect a descendant of the containment container.

    This doesn't work on all browsers.

    This text turns blue when it can no longer be scrolled up, and red as soon as it can no longer be scrolled down. This required two container query requests.
     
  • @container id scroll-state(snapped: block) { ... }

    The snapped descriptor lets you check if the containment container is anchored. So it needs to be in a container with scroll anchoring.

    • none: the snapped element doesn't play any role.
    • x: the container is an element with snapping along X.
    • y: the container is an element with snapping along Y.
    • block: the container is an element with snapping along the block axis.
    • inline: the container is an element with snapping along the lines axis.
    • both: The container is an element with snapping along both axes.

    Here the containment container is multiple. It has the ability to anchor during scrolling (scroll-snap-align:center). It of course receives the properties container-name and container-type which make it a containment container, along with some other formatting properties.
    Above it is the scrolling container with anchoring (id=container) with the property scroll-snap-type:y mandatory.
    If needed, refer to the tutorial on scrolling with snaps.

    By using the scroll bar, you anchor each of the elements one by one. The one that's anchored gets a colored background.

    This doesn't work on all browsers.


    1
     

    2
     

    3
     

    4
     
     
     
  • @container id style(propriété:valeur) { ... }

    The style() function lets you check for a property that would be applied to the container, either directly or through inheritance. For now (2026), it only works with custom properties.

    This doesn't work on all browsers.

    This text turns red as soon as its alignment is centered.
    This second paragraph isn't centered.

Browsers compatibility with the @container at-rule.

The @container at-rule is well recognized when it comes to tests on container dimensions, but not yet for scrolling tests with scroll-state() or style tests with styles().

Column 1
Correct handling by browsers of the @container at-rule which greatly facilitates the writing of components.
Column 2
Browser support for the scroll-state() function with the @container at-rule.
Column 3
Recognition by browsers of the style() function in the syntax of the @container at-rule.
1
@container
at-rule
2
Function scroll-state()
in @container
3
Function style()
in @container
Estimated overall support.
94%
63%
0%

Browsers on computers :

Mobile browsers :

Outdated or marginal browsers :

Internet Explorer

UC Browser pour Androïd

Opéra Mobile

QQ Browser

Baidu Browser

Samsung Internet

Chrome

Edge

Chrome pour Androïd

Androïd Brower

Firefox pour Androïd

Opéra

Safari

Safari sur IOS

Firefox

KaiOS Browser

Opéra mini

Evolution of the @container at-rule.

  • CSS Containment Module Level 3

    Level 3 of this specification specifically defines container-relative units of measurement, in order to make each element on the page independent.

    Regarding @container Introduction of "containment" techniques and the @container at-rule.
    WD
    December 21, 2021
    Working Draft.
    CR
    PR
    REC

See also, regarding containment techniques.

The properties and other concepts related to confinement are described in the specification CSS Containment Module.

Properties:

contain
Langue française
Optimization property, to facilitate and speed up the layout work of complex pages.
container
Langue française
Defines the characteristics of a container that can be used in a container query (confined element context).
container-name
Langue française
Assigns an identifier to an element to make it a container usable in a container query (contained element context).
container-type
Langue française
Defines the type of a container that can be used in a container query (contained element context).
content-visibility
Langue française
Defines whether the element's content (including sub-elements) should be rendered or not.

At-rules:

@container
Allows you to write conditional CSS rules based on the characteristics of the container.