CSS Containment Module Level 3

Editor’s Draft,

More details about this document
This version:
https://drafts.csswg.org/css-contain-3/
Latest published version:
https://www.w3.org/TR/css-contain-3/
Previous Versions:
Test Suite:
https://test.csswg.org/harness/results/css-contain-1_dev/
Feedback:
CSSWG Issues Repository
Inline In Spec
Editors:
Tab Atkins (Google)
Florian Rivoal (On behalf of Bloomberg)
Miriam E. Suzanne (Invited Expert)
Suggest an Edit for this Spec:
GitHub Editor

Abstract

This CSS module describes the contain property, which indicates that the element’s subtree is independent of the rest of the page. This enables heavy optimizations by user agents when used well.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-contain” in the title, like this: “[css-contain] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 03 November 2023 W3C Process Document.

1. Introduction

This is a diff spec over CSS Containment Level 2. It is currently an Exploratory Working Draft: if you are implementing anything, please use Level 2 as a reference. We will merge the Level 2 text into this draft once it reaches CR.

1.1. Module Interactions

This document defines new features not present in earlier specifications. In addition, it aims to replace and supersede [CSS-CONTAIN-1] once stable.

1.2. Value Definitions

This specification follows the CSS property definition conventions from [CSS2] using the value definition syntax from [CSS-VALUES-3]. Value types not defined in this specification are defined in CSS Values & Units [CSS-VALUES-3]. Combination with other CSS modules may expand the definitions of these value types.

In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the CSS-wide keywords as their property value. For readability they have not been repeated explicitly.

2. Strong Containment: the contain property

CSS Containment 2 § 2 Strong Containment: the contain property

Name: contain
Value: none | strict | content | [ [size | inline-size] || layout || style || paint ]
inline-size
This value turns on inline-size containment for the element. This prevents the inline-size of its principal box from directly depending on its contents.

Note: There can still be indirect dependencies, see § 3.1 Inline-Size Containment.

3. Types of Containment

CSS Containment 2 § 3 Types of Containment

3.1. Inline-Size Containment

Giving an element inline-size containment applies size containment to the inline-axis sizing of its principal box. This means the inline-axis intrinsic sizes of the principal box are determined as if the element had no content. However, content continues to impact the box’s block-axis intrinsic sizes as usual, and the box is allowed to fragment normally in the block axis.

Note: In some cases, a box’s block-axis intrinsic sizes can impact layout in the parent formatting context in ways that affect the box’s inline size (e.g. by triggering scrollbars on an ancestor element), creating a dependency of the box’s inline size on its own content. If this changed inline size results in a different block size, that new block size can loop into further impacting the parent formatting context, but not in a way that reverts it to the previously-problematic layout.

For example, if scrollbars were introduced, they are not then removed, even if the consequent block size is small enough to not need them; or if a box’s logical height collides with a lower-placed float and is cleared down to where it also has more available inline space and thus becomes short enough to not have collided, it is not them moved back up to its previous problematic size and position.

Thus, although inline-size containment prevents the box’s content from directly affecting its inline size through its inline-axis intrinsic sizes, its inline size can still indirectly depend on its contents by their effect on its block size.

In general, the relationship between an element’s inline size and it’s block size is unpredictable and non-monotonic, with the block size capable of shifting up and down arbitrarily as the inline size is changed. Infinite cycles are prevented by ensuring that layout does not revert to a previous (known-problematic) state, even if a naive analysis of the constraints would allow for such; in other words, layout always “moves forward”. We believe that current CSS layout specifications incorporate such rules, but to the extent that they don’t, please inform the CSSWG so that these errors can be corrected.

Consider this example, where float placement creates a dependency of block sizes on inline sizes:
<section style="width: 200px; border: solid; display: flow-root;">
  <!-- floated elements that impact the available space -->
  <div style="float: left; width: 50px; height: 80px; background: blue;"></div>
  <div style="float: right; width: 50px; height: 80px; background: blue;"></div>
  <div style="float: left; width: 160px; height: 80px; background: navy;"></div>

  <!-- parent layout, determining context -->
  <article style="border: solid orangered; display: flow-root; min-width: min-content">
    <div style="background: orange; aspect-ratio: 1/1;">
      Article
    </div>
  </article>
</section>
Article

The block layout algorithm will first place the floating boxes, with the first two sitting in the left and right corners of the container, and the third, being too wide to fit between, being pushed below them.

The following article will then be laid out. Because it is display: flow-root, it cannot intersect any floats, and thus must take them into account when figuring out how to size and position itself.

The layout engine first attempts to place the article flush with the top of the container, resulting a 100px width, plenty wide enough to accommodate its min-content size. However, due to the aspect-ratio of its child, this would cause the article to be 100px tall as well, which would intersect the third float 80px below, so this layout opportunity is discarded.

It then attempts to position the article flush with the top of the third float, in the narrow 40px-wide space to its right. However, since the article’s min-width makes it too large to fit in the 40px-wide space beside the third float, it shifts below that one as well, forming a 200px square below all the floated boxes.

Article

If the min-width is removed from the article, or if inline-size containment is added to either the article or header (causing min-width: min-content to resolve to zero), then the article will fit as a 40px square next to the final floated div (possibly with some of its content overflowing).

At this point, the width and height of the article (40px each) would fit back in the first considered space, flush with the top of the container. However, the box is not returned to the previous position, because the layout engine knows already that this position would result in an invalid layout.

Giving an element inline-size containment has no effect if any of the following are true:

4. Container Queries

While media queries provide a method to query aspects of the user agent or device environment that a document is being displayed in (such as viewport dimensions or user preferences), container queries allow testing aspects of elements within the document (such as box dimensions or computed styles).

By default, all elements are query containers for the purpose of container style queries, and can be established as query containers for container size queries by specifying the additional query types using the container-type property (or the container shorthand). Style rules applying to a query container’s shadow-including descendants can be conditioned by querying against it, using the @container conditional group rule.

For example, we can define the main content area and sidebar as containers, and then describe a .media-object that changes from vertical to horizontal layout depending on the size of its container:
main, aside {
  container: my-layout / inline-size;
}

.media-object {
  display: grid;
  grid-template: 'img' auto 'content' auto / 100%;
}

@container my-layout (inline-size > 45em) {
  .media-object {
    grid-template: 'img content' auto / auto 1fr;
  }
}

Media objects in the main and sidebar areas will each respond to their own container context.

For selectors with pseudo elements, query containers can be established by the shadow-including inclusive ancestors of the ultimate originating element.

It follows that:
A ::before selector querying the size of the originating element:
<style>
  #container {
    width: 100px;
    container-type: inline-size;
  }
  @container (inline-size < 150px) {
    #inner::before {
      content: "BEFORE";
    }
  }
</style>
<div id=container>
  <span id=inner></span>
</div>
A ::slotted() selector for styling a shadow host child can query a container in the shadow tree:
<div id=host style="width:200px">
  <template shadowroot=open>
    <style>
      #container {
        width: 100px;
        container-type: inline-size;
      }
      @container (inline-size < 150px) {
        ::slotted(span) {
          color: green;
        }
      }
    </style>
    <div id=container>
      <slot />
    </div>
  </template>
  <span id=slotted>Green</span>
</div>

4.1. Creating Query Containers: the container-type property

Name: container-type
Value: normal | size | inline-size
Initial: normal
Applies to: all elements
Inherited: no
Percentages: n/a
Computed value: specified keyword
Canonical order: per grammar
Animation type: not animatable

The container-type property establishes the element as a query container for the purpose of container queries that require explicit containment (such as container size queries), allowing style rules styling its descendants to query various aspects of its sizing and layout, and respond accordingly.

Unless otherwise noted, all elements are query containers for the purpose of container queries that do not require explicit containment (such as container style queries), regardless of the specified container-type.

Values have the following meanings:

size
Establishes a query container for container size queries on both the inline and block axis. Applies layout containment, style containment, and size containment to the principal box.
inline-size
Establishes a query container for container size queries on the container’s own inline axis. Applies layout containment, style containment, and inline-size containment to the principal box.
normal
The element is not a query container for any container size queries, but remains a query container for container style queries.
For example, authors can create container-responsive typography, adjusting font-size, line-height, and other typographic concerns based on the size of a container:
aside, main {
  container-type: inline-size;
}

h2 { font-size: 1.2em; }

@container (width > 40em) {
  h2 { font-size: 1.5em; }
}

The 40em value used in the query condition is relative to the computed value of font-size on the relevant query container.

Containers can also expose computed style values for querying. This can be useful for toggling behavior across multiple properties:
section {
  container-type: style;
}

@container style(--cards: small) {
  article {
    border: thin solid silver;
    border-radius: 0.5em;
    padding: 1em;
  }
}

4.2. Naming Query Containers: the container-name property

Name: container-name
Value: none | <custom-ident>+
Initial: none
Applies to: all elements
Inherited: no
Percentages: n/a
Computed value: the keyword none, or an ordered list of identifiers
Canonical order: per grammar
Animation type: not animatable

The container-name property specifies a list of query container names. These names can be used by @container rules to filter which query containers are targeted.

none
The query container has no query container name.
<custom-ident>
Specifies a query container name as an identifier. The keywords none, and, not, and or are excluded from this <custom-ident>.
In some cases, we want to query aspects of a specific container, even if it’s not the nearest ancestor container. For example, we might want to query the height of a main content area, and the width of a more nested inline-container.
main {
  container-type: size;
  container-name: my-page-layout;
}

.my-component {
  container-type: inline-size;
  container-name: my-component-library;
}

@container my-page-layout (block-size > 12em) {
  .card { margin-block: 2em; }
}

@container my-component-library (inline-size > 30em) {
  .card { margin-inline: 2em; }
}

4.3. Creating Named Containers: the container shorthand

Name: container
Value: <'container-name'> [ / <'container-type'> ]?
Initial: see individual properties
Applies to: see individual properties
Inherited: see individual properties
Percentages: see individual properties
Computed value: see individual properties
Animation type: see individual properties
Canonical order: per grammar

The container shorthand property sets both container-type and container-name in the same declaration. If <'container-type'> is omitted, it is reset to its initial value.

We can define both a container-type and container-name using the shorthand syntax:
main {
  container: my-layout / size;
}

.grid-item {
  container: my-component / inline-size;
}

4.4. Container Queries: the @container rule

The @container rule is a conditional group rule whose condition contains a container query, which is a boolean combination of container size queries and/or container style queries. Style declarations within the <block-contents> block of an @container rule are filtered by its condition to only match when the container query is true for their element’s query container.

The syntax of the @container rule is:

@container <container-condition># {
  <block-contents>
}

where:

<container-condition> = [ <container-name> ]? <container-query>
<container-name> = <custom-ident>
<container-query>     = not <query-in-parens>
                      | <query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]
<query-in-parens>     = ( <container-query> )
                      | ( <size-feature> )
                      | style( <style-query> )
                      | <general-enclosed>

<style-query>         = not <style-in-parens>
                      | <style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ]
                      | <style-feature>
<style-in-parens>     = ( <style-query> )
                      | ( <style-feature> )
                      | <general-enclosed>

The keywords none, and, not, and or are excluded from the <custom-ident> above.

For each element, the query container to be queried is selected from among the element’s ancestor query containers that are established as a valid query container for all the container features in the <container-query>. If the <container-query> contains unknown or unsupported container features, no query container will be selected for that <container-condition>. The optional <container-name> filters the set of query containers considered to just those with a matching query container name.

Once an eligible query container has been selected for an element, each container feature in the <container-query> is evaluated against that query container. If no ancestor is an eligible query container, then the container query is unknown for that element. As with media queries, <general-enclosed> evaluates to unknown.

If a container query includes multiple <container-condition>s, each condition will select it’s own query container, and evaluate independently. A container query is true if any of its component <container-condition>s are true, and false only if all of its component <container-condition>s are false.

As with media queries, we can string together multiple queries in a single condition:
@container card (inline-size > 30em) and style(--responsive: true) {
  /* styles */
}

The styles above will only be applied if there is an ancestor container named "card" that meets both the inline-size and style conditions.

We can also combine multiple conditions into a list, with each condition evaluating against a different container:

@container card (inline-size > 30em), style(--large: true) {
  /* styles */
}

The styles above will be applied if there is an ancestor container named "card" that meets the inline-size condition or the nearest style container meets the style condition.

Style rules defined on an element inside multiple nested container queries apply when all of the wrapping container queries are true for that element.

Note: Nested container queries can evaluate in relation to different containers, so it is not always possible to merge the individual <container-condition>s into a single query.

Using a single comma-separated container query, we can query multiple containers:
@container card (inline-size > 30em), style(--responsive: true) {
  /* styles */
}

The styles above will apply for an element inside either a container named "card" that meets the inline-size condition, or a container meeting the style condition.

In order to require that all conditions are met while querying multiple containers, we would need to nest multiple queries:

@container card (inline-size > 30em) {
  @container style(--responsive: true) {
    /* styles */
  }
}

The styles above will only be applied if there is both an ancestor container named "card" that meets the inline-size condition, and an ancestor container meeting the style condition.

Global, name-defining at-rules such as @keyframes or @font-face or @layer that are defined inside container queries are not constrained by the container query conditions.

4.5. Animated Containers

A change in the evaluation of a container query must be part of a style change event, even when the change occurred because of animation effects.

A transition on a sibling element can indirectly affect the size of a container, triggering style change events whenever container queries change their evaluation as a result:
main {
  display: flex;
  width: 300px;
}

#container {
  container-type: inline-size;
  flex: 1;
}

/* Resolved width is initially 200px, but changes as the transition
   on #sibling progresses. */
#inner {
  transition: 1s background-color;
  background-color: tomato;
}

/* When this container query starts (or stops) applying, a transition
   must start on background-color on #inner. */
@container (width <= 150px) {
  #inner {
    background-color: skyblue;
  }
}

#sibling {
  width: 100px;
  transition: width 1s;
}

#sibling:hover {
  width: 200px;
}
<main>
  <div id=container>
    <div id=inner>Inner</div>
  </div>
  <div id=sibling>Sibling</div>
</main>

Changes in computed values caused by container query length units must also be part of a style change event.

5. Container Features

A container feature queries a specific aspect of a query container.

5.1. Size Container Features

A container size query allows querying the size of the query container’s principal box. It is a boolean combination of individual size features (<size-feature>) that each query a single, specific dimensional feature of the query container. The syntax of a <size-feature> is the same as for a media feature: a feature name, a comparator, and a value. [mediaqueries-5] The boolean syntax and logic combining size features into a size query is the same as for CSS feature queries. (See @supports. [CSS-CONDITIONAL-3])

If the query container does not have a principal box, or the principal box is not a layout containment box, or the query container does not support container size queries on the relevant axes, then the result of evaluating the size feature is unknown.

Relative length units (including container query length units) and custom properties in container query conditions are evaluated based on the computed values of the query container.

Note: This is different from the handling of relative units in media queries.

Note: If custom property substitution results in an invalid value for the size feature, it is handled the same as other invalid feature values, and the result of the size feature is unknown.

For example, query containers with different font-sizes will evaluate em-based queries relative to their own font sizes:
aside, main {
  container-type: inline-size;
}

aside { font-size: 16px; }
main { font-size: 24px; }

@container (width > 40em) {
  h2 { font-size: 1.5em; }
}

The 40em value used in the query condition is relative to the computed value of font-size on the relevant query container:

Similarly, query containers will evaluate var()-based queries relative to their own computed value of the custom property:
aside, main {
  container-type: inline-size;
}

aside { --query: 300px; }
main { --query: 500px; }

@container (width > var(--query)) {
  h2 { font-size: 1.5em; }
}

The var(--query) value used in the query condition is substituted with the computed value of the --query custom property on the relevant query container:

5.1.1. Width: the width feature

Name: width
For: @container
Value: <length>
Type: range

The width container feature queries the width of the query container’s content box.

5.1.2. Height: the height feature

Name: height
For: @container
Value: <length>
Type: range

The height container feature queries the height of the query container’s content box.

5.1.3. Inline-size: the inline-size feature

Name: inline-size
For: @container
Value: <length>
Type: range

The inline-size container feature queries the size of the query container’s content box in the query container’s inline axis.

5.1.4. Block-size: the block-size feature

Name: block-size
For: @container
Value: <length>
Type: range

The block-size container feature queries the size of the query container’s content box in the query container’s block axis.

5.1.5. Aspect-ratio: the aspect-ratio feature

Name: aspect-ratio
For: @container
Value: <ratio>
Type: range

The aspect-ratio container feature is defined as the ratio of the value of the width container feature to the value of the height container feature.

5.1.6. Orientation: the orientation feature

Name: orientation
For: @container
Value: portrait | landscape
Type: discrete
portrait
The orientation container feature is portrait when the value of the height container feature is greater than or equal to the value of the width container feature.
landscape
Otherwise orientation is landscape.

5.2. Style Container Features

A container style query allows querying the computed values of the query container. It is a boolean combination of individual style features (<style-feature>) that each query a single, specific property of the query container. The syntax of a <style-feature> is either the same as for a valid declaration [CSS-SYNTAX-3], a supported CSS property, or a <custom-property-name>.

Its query evaluates to true if the computed value of the given property on the query container matches the given value (which is also computed with respect to the query container), and false otherwise.

A style feature without a value evaluates to true if the computed value is different from the initial value for the given property.

The boolean syntax and logic combining style features into a style query is the same as for CSS feature queries. (See @supports. [CSS-CONDITIONAL-3])

Style features that query a shorthand property are true if the computed values match for each of its longhand properties, and false otherwise.

Cascade-dependent keywords, such as revert and revert-layer, are invalid as values in a style feature, and cause the container style query to be false.

Note: The remaining non-cascade-dependent CSS-wide keywords are computed with respect to the query container, the same as other values.

6. Container Relative Lengths: the cqw, cqh, cqi, cqb, cqmin, cqmax units

Container query length units specify a length relative to the dimensions of a query container. Style sheets that use container query length units can more easily move components from one query container to another.

The container query length units are:

Informative Summary of Container Units
unit relative to
cqw 1% of a query container’s width
cqh 1% of a query container’s height
cqi 1% of a query container’s inline size
cqb 1% of a query container’s block size
cqmin The smaller value of cqi or cqb
cqmax The larger value of cqi or cqb

For each element, container query length units are evaluated as container size queries on the relevant axis (or axes) described by the unit. The query container for each axis is the nearest ancestor container that accepts container size queries on that axis. If no eligible query container is available, then use the small viewport size for that axis.

Note: In some cases cqi and cqb units on the same element will evaluate in relation to different query containers. Similarly, cqmin and cqmax units represent the larger or smaller of the cqi and cqb units, even when those dimensions come from different query containers.

Child elements do not inherit the relative values as specified for their parent; they inherit the computed values.

Authors can ensure that container query length units have an appropriate query container by applying them inside a container query that relies on the same container-type. Custom fallback values can be defined outside the container query:
/* The fallback value does not rely on containment */
h2 { font-size: 1.2em; }

@container (inline-size >= 0px) {
  /* only applies when an inline-size container is available */
  h2 { font-size: calc(1.2em + 1cqi); }
}

7. APIs

7.1. The CSSContainerRule interface

The CSSContainerRule interface represents a @container rule.

[Exposed=Window]
interface CSSContainerRule : CSSConditionRule {
    readonly attribute CSSOMString containerName;
    readonly attribute CSSOMString containerQuery;
};
conditionText of type CSSOMString (CSSContainerRule-specific definition for attribute on CSSConditionRule)
The conditionText attribute (defined on the CSSConditionRule parent rule), on getting, must return a value as follows:
The @container rule has an associated <container-name>
The result of getting the containerName and containerQuery attributes, joined by a single whitespace.
Otherwise
The result of getting the containerQuery attribute.
containerName of type CSSOMString
The containerName attribute, on getting, must return a value as follows:
The @container rule has an associated <container-name>
The result of serializing that <container-name>.
Otherwise
An empty string.
containerQuery of type CSSOMString
The containerQuery attribute, on getting, must return the <container-query> that was specified, without any logical simplifications, so that the returned query will evaluate to the same result as the specified query in any conformant implementation of this specification (including implementations that implement future extensions allowed by the <general-enclosed> extensibility mechanism in this specification). In other words, token stream simplifications are allowed (such as reducing whitespace to a single space or omitting it in cases where it is known to be optional), but logical simplifications (such as removal of unneeded parentheses, or simplification based on evaluating results) are not allowed.

Container Queries should have a matchContainer method. This will be modeled on matchMedia() and the MediaQueryList interface, but applied to Elements rather than the Window. When measuring layout sizes, it behaves Similar to resizeObserver, but it provides the additional Container Query syntax and features. [Issue #6205]

8. Suppressing An Element’s Contents Entirely: the content-visibility property

Name: content-visibility
Value: visible | auto | hidden
Initial: visible
Applies to: elements for which size containment can apply
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Animation type: see § 8.1 Animating and Interpolating content-visibility

CSS Containment 2 § 4 Suppressing An Element’s Contents Entirely: the content-visibility property

8.1. Animating and Interpolating content-visibility

In general, the content-visibility property’s animation type is discrete. However, similar to interpolation of visibility (see Web Animations §  Animation of visibility), during interpolation between hidden and any other content-visibility value, p values between 0 and 1 map to the non-hidden value.

9. Privacy Considerations

CSS Containment 2 § 5 Privacy Considerations

10. Security Considerations

CSS Containment 2 § 6 Security Considerations

Appendix A. Changes

This appendix is informative.

Changes since the 18 August 2022 Working Draft

Significant changes since the 18 August 2022 Working Draft include:

Changes since the 21 December 2021 First Public Working Draft

Significant changes since the 21 December 2021 First Public Working Draft include:

Changes from CSS Containment Level 2

CSS Containment 2 § A Changes

Acknowledgments

Comments and previous work from Adam Argyle, Amelia Bellamy-Royds, Anders Hartvoll Ruud, Brian Kardell, Chris Coyier, Christopher Kirk-Nielsen, David Herron, Elika J. Etemad (fantasai), Eric Portis, Ethan Marcotte, Geoff Graham, Gregory Wild-Smith, Ian Kilpatrick, Jen Simmons, Kenneth Rohde Christiansen, L. David Baron, Lea Verou, Martin Auswöger, Martine Dowden, Mike Riethmuller, Morten Stenshorne, Nicole Sullivan, Rune Lillesveen, Scott Jehl Scott Kellum, Stacy Kvernmo, Theresa O’Connor, Una Kravets, and many others have contributed to this specification.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Tests

Tests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.


Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-ANIMATIONS-1]
David Baron; et al. CSS Animations Level 1. URL: https://drafts.csswg.org/css-animations/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. URL: https://drafts.csswg.org/css-box-4/
[CSS-BREAK-3]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. URL: https://drafts.csswg.org/css-break/
[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS Cascading and Inheritance Level 4. URL: https://drafts.csswg.org/css-cascade-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. URL: https://drafts.csswg.org/css-cascade-5/
[CSS-CONDITIONAL-3]
David Baron; Elika Etemad; Chris Lilley. CSS Conditional Rules Module Level 3. URL: https://drafts.csswg.org/css-conditional-3/
[CSS-CONTAIN-1]
Tab Atkins Jr.; Florian Rivoal. CSS Containment Module Level 1. URL: https://drafts.csswg.org/css-contain-1/
[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS Containment Module Level 2. URL: https://drafts.csswg.org/css-contain-2/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. URL: https://drafts.csswg.org/css-display/
[CSS-DISPLAY-4]
CSS Display Module Level 4. Editor's Draft. URL: https://drafts.csswg.org/css-display-4/
[CSS-FONTS-5]
Chris Lilley. CSS Fonts Module Level 5. URL: https://drafts.csswg.org/css-fonts-5/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. URL: https://drafts.csswg.org/css-sizing-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. URL: https://drafts.csswg.org/css-syntax/
[CSS-TRANSITIONS-1]
David Baron; et al. CSS Transitions. URL: https://drafts.csswg.org/css-transitions/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. URL: https://drafts.csswg.org/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. URL: https://drafts.csswg.org/css-values-4/
[CSS-VARIABLES-2]
CSS Custom Properties for Cascading Variables Module Level 2. Editor's Draft. URL: https://drafts.csswg.org/css-variables-2/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. URL: https://drafts.csswg.org/css-writing-modes-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. URL: https://drafts.csswg.org/css2/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). URL: https://drafts.csswg.org/cssom/
[CSSOM-VIEW-1]
Simon Pieters. CSSOM View Module. URL: https://drafts.csswg.org/cssom-view/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[MEDIAQUERIES-5]
Dean Jackson; et al. Media Queries Level 5. URL: https://drafts.csswg.org/mediaqueries-5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. URL: https://drafts.csswg.org/selectors/
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web Animations. URL: https://drafts.csswg.org/web-animations-1/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

Informative References

[CSS-FONTS-4]
Chris Lilley. CSS Fonts Module Level 4. URL: https://drafts.csswg.org/css-fonts-4/
[CSS-POSITION-4]
CSS Positioned Layout Module Level 4. Editor's Draft. URL: https://drafts.csswg.org/css-position-4/
[CSS-PSEUDO-4]
Daniel Glazman; Elika Etemad; Alan Stearns. CSS Pseudo-Elements Module Level 4. URL: https://drafts.csswg.org/css-pseudo-4/
[CSS-SCOPING-1]
Tab Atkins Jr.; Elika Etemad. CSS Scoping Module Level 1. URL: https://drafts.csswg.org/css-scoping/
[CSS-SHADOW-PARTS-1]
Tab Atkins Jr.; Fergal Daly. CSS Shadow Parts. URL: https://drafts.csswg.org/css-shadow-parts/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons. CSS Box Sizing Module Level 4. URL: https://drafts.csswg.org/css-sizing-4/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification. URL: https://drafts.csswg.org/css2/

Property Index

Name Value Initial Applies to Inh. %ages Anim­ation type Canonical order Com­puted value
container <'container-name'> [ / <'container-type'> ]? see individual properties see individual properties see individual properties see individual properties see individual properties per grammar see individual properties
container-name none | <custom-ident>+ none all elements no n/a not animatable per grammar the keyword none, or an ordered list of identifiers
container-type normal | size | inline-size normal all elements no n/a not animatable per grammar specified keyword
content-visibility visible | auto | hidden visible elements for which size containment can apply no n/a see per grammar as specified

@container Descriptors

Name Value Initial Type
aspect-ratio <ratio> range
block-size <length> range
height <length> range
inline-size <length> range
orientation portrait | landscape discrete
width <length> range

IDL Index

[Exposed=Window]
interface CSSContainerRule : CSSConditionRule {
    readonly attribute CSSOMString containerName;
    readonly attribute CSSOMString containerQuery;
};

Issues Index

This is a diff spec over CSS Containment Level 2. It is currently an Exploratory Working Draft: if you are implementing anything, please use Level 2 as a reference. We will merge the Level 2 text into this draft once it reaches CR.
CSS Containment 2 § 2 Strong Containment: the contain property
CSS Containment 2 § 3 Types of Containment
In general, the relationship between an element’s inline size and it’s block size is unpredictable and non-monotonic, with the block size capable of shifting up and down arbitrarily as the inline size is changed. Infinite cycles are prevented by ensuring that layout does not revert to a previous (known-problematic) state, even if a naive analysis of the constraints would allow for such; in other words, layout always “moves forward”. We believe that current CSS layout specifications incorporate such rules, but to the extent that they don’t, please inform the CSSWG so that these errors can be corrected.
Container Queries should have a matchContainer method. This will be modeled on matchMedia() and the MediaQueryList interface, but applied to Elements rather than the Window. When measuring layout sizes, it behaves Similar to resizeObserver, but it provides the additional Container Query syntax and features. [Issue #6205]
CSS Containment 2 § 4 Suppressing An Element’s Contents Entirely: the content-visibility property
CSS Containment 2 § 5 Privacy Considerations
CSS Containment 2 § 6 Security Considerations
CSS Containment 2 § A Changes
MDN

CSSContainerRule/containerName

In all current engines.

Firefox110+Safari17+Chrome111+
Opera?Edge111+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSContainerRule/containerQuery

In all current engines.

Firefox110+Safari17+Chrome111+
Opera?Edge111+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

CSSContainerRule

In all current engines.

Firefox110+Safari16+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@container

In only one current engine.

FirefoxNoneSafariNoneChrome111+
Opera?Edge111+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

@container

In all current engines.

Firefox110+Safari16+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

contain#inline-size

In all current engines.

Firefox101+Safari15.4+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

container-name

In all current engines.

Firefox110+Safari16+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

container-type

In all current engines.

Firefox110+Safari16+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

container

In all current engines.

Firefox110+Safari16+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?