Skip to content
This repository was archived by the owner on Apr 24, 2023. It is now read-only.

dbaron/container-queries-implementability

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 

Repository files navigation

This repository is no longer active. The proposal here had some influence on the development of Container Queries in CSS. Container Queries are now part of the CSS Containment Module Level 3 and are usable across most major browser engines. Issues on container queries should be discussed in the CSS Working Group's repository.

Thoughts on an implementable path forward for Container Queries

The idea of Container Queries has been discussed widely, such as in WICG/container-queries and in w3c/csswg-drafts#3852. CSS authors want a way to use a feature like media queries on a part of the page. Many of the use cases underlying this desire relate to things that are component-like, that is, pieces of a web page that might be used in different webpages. Authors wish to construct a component whose appearance responds to its size, but they want this component to be a part of the webpage that contains it.

Dependence on containment

The main reason this is theoretically difficult is that this requires that styles depend on the size of the component, yet given how CSS works, the styles in a component influence its size. Arbitrarily breaking this loop would both give weird results and would interfere with browser optimizations related to incremental relayout.

In w3c/csswg-drafts#1031 I proposed a way around this, based on the ideas in the CSS Containment specification. In particular, I believe that container queries should be possible if an element has both layout containment and has size containment in the axis used for the container queries. The problem here is that we don't have a definition of size containment in a single axis.

I believe that it's plausible to revise the definition of size containment to define a variant that applies in a single axis (which would probably be named width, height, block-size, or inline-size) by revising the definition (perhaps after being amended per w3c/csswg-drafts#4741) to say "when calculating the size of the containing block in the given axis". (What this means, underneath, probably needs to be defined per layout system, as does the existing definition.)

Containment in a single axis

To explain what containment in a single axis means, we need to define it for each display type.

The current definition of containment uses a convenient shorthand: define contain: size to behave as though the element has no contents. This works in both dimensions. Implementing this is not quite so trivial for implementations: implementations need some custom code in the implementation of each display type, and maybe in more than one place for some of them, to act as though the element has no contents. But it is, nonetheless, a clear and simple definition that implementers can apply, although it might require a bit of work for implementers to find all the places in the code that they need to apply it.

Describing containment in a single dimension is harder from a specification perspective, since the specification can no longer use the shortcut of assuming that the element has no contents. Roughly, it requires that we make that sort of assumption in some places but not others, so as to influence one dimension but not the other. So here I'm proposing to redefine containment in each axis by having the spec define each effect that containment has.

These definitions have to ensure two things:

  • the combination of the effects that you'd get from contain: width combined with contain: height (or contain: block-size combined with contain: inline-size) should add up to being equivalent to the current definition of contain: size: act as though the box has no contents.
  • containment of one dimension does mean that the contents don't affect the size in that dimension.

Ideally, the definition will also ensure that the computation of the size in the second dimension works in a way that is as close as possible to how it would work without containment in the first dimension.

Or, to put it another way, this approach means that the specification needs to take the approach that I believe implementations already take (at least Gecko's), which is adding a test in various places in the layout code to have some specific change in behavior when containment is present.

TODO: flesh this definition out more and go through the feedback on #4741 ... and figure out if this whole thing has a chance of actually working!

ISSUE: Florian points out that the definitions here aren't really sufficient, because a size in one dimension can, through ancestors, influence the size in the other dimension, for example through causing a scrollbar to be created. Need to work out whether this makes this proposal not workable, or whether there's a way around it.

... inline-size containment for display:block

The computation of intrinsic sizes in the inline axis assumes that the block has no contents.

There is no effect on layout since block layout doesn't generally produce output in the inline dimension.

(It's not clear what the effect on intrinsic sizes in the block axis should be, but it will perhaps be clearer once it's clearer what intrinsic sizes in the block axis are.)

... block-size containment for display:block

First, the computation of intrinsic sizes in the block axis (whatever they mean in the first place) assumes that the block has no contents.

Second, the final block-size computation during layout also assumes that the block has no contents.

... inline-size containment for display:table

The computation of both intrinsic sizes in the inline axis and the inline-size computed during layout assume that the table has no contents.

... block-size containment for display:table

First, the computation of intrinsic sizes in the block axis (whatever they mean in the first place) assumes that the table has no contents.

Second, the final block-size computation during layout also assumes that the table has no contents. It's not clear to me what the resulting row block-sizes are, but they're presumably the same as whatever happens for size containment.

... inline-size containment for display:table-cell

same as for display: block

... block-size containment for display:table-cell

same as for display: block (with the caveat that the final block-size computation during layout is more complicated)

... containment for display:flex in the main axis

Both the max-content main size and the min-content main size are 0, since that is the result that the normal rules would produce if there are no flex items.

No specfic change in the layout algorithm is needed because the part of the layout algorithm where the contents influence the size uses the intrinsic sizes.

... containment for display:flex in the cross axis

Both the max-content cross size and the min-content cross size are 0, since that is the result that the normal rules would produce if there are no flex items.

No specfic change in the layout algorithm is needed because the part of the layout algorithm where the contents influence the size uses the intrinsic sizes.

... inline-size containment for display:grid

FIXME: TO BE WRITTEN

... block-size containment for display:grid

FIXME: TO BE WRITTEN

... inline-size containment for multi-column

FIXME: TO BE WRITTEN

... block-size containment for multi-column

FIXME: TO BE WRITTEN

... more cases that need to be handled?

Scope-based CSS cascading

The proposal I'm making here addresses the need for container queries, but it also addresses a second need that I'd like to explain a little further. It adds support for a different type of CSS cascading priority.

CSS cascading has the existing concept of specificity. This concept often doesn't work very well for authors of CSS. I believe that one of the reasons for this is that the specificity is based on selectors that match anywhere in the tree, and doesn't consider the proximity of the element selected by a selector to the target of the selector.

Cascading Level 4 has added the concept of scope to the cascade level. I think this concept is currently only accessible through Web Components (although I'm not sure it's accessible through them). (It was previously accessible through scoped