Skip to main
Article

Partial Feature Queries, Relaxed Layout Containment, and More

CSS Working Group updates from July

Over the last month, the CSS Working Group has determined we can loosen containment restrictions for query containers, and agreed on a syntax for special-case support queries (like support for the gap property in a flex context, or support for align-content in a block flow context).

For more, you can access CSS Working Group meeting minutes on the W3C mailing list archive. That’s also a good place to see the agenda for upcoming meetings. Regular meetings happen every Wednesday, with the agenda generally sent one day in advance. This post highlights updates from:

Note:

This is part of a series providing updates around my work on the CSS Working Group.

These contributions take a lot of time and effort. If you’re interested in supporting our open-source CSS work, consider becoming a GitHub sponsor, or contributing to our Open Collective.

Container Queries have officially moved out of the CSS Containment Module, and into CSS Conditional Rules Module (Level 5). This is the same specification module that defines the @media and @supports rules.

Both levels 4 and 5 are currently written as ‘diff specs’ – only showing changes from the previous level, rather than the entire specification. Level 4 defined the @supports selector() selector-support feature query, and is already a Candidate Recommendation:

By publishing a Candidate Recommendation, a working group is expressing that it considers the specification complete and that it has resolved all known issues.

It’s a bit strange to me that it would still be treated as a ‘diff’, with the generic /css-conditional/ url still pointing at level 3 – but these things happen. The spec process is not always simple and linear.

Just to make this web of CSS modules even more confusing: media queries also have a distinct Media Queries module. That module defines what media features can be queried, while the Conditional Rules module only defines the at-rule we use inside CSS stylesheets.

A new preference-query API

Media Queries Module Level 5 defines a number of user preference media features, which have been around for a while now:

One of those queries is not like the others, and you can tell the difference from the name. The forced-colors setting is the only one enforced by browsers – all the others are ignorable. If we (as authors) never query the user preference for ‘reduced motion’, it will have no effect on our site.

Users can generally change these preferences at either the operating system level, or inside their browser – depending on the OS, browser, and setting in question. But at this point, there’s no way for users to change their preference for a specific website, and save that change across multiple visits. We can work around that by individually providing (for example) light/dark toggles, and then saving the choice to local storage or a cookie. But returning visitors will still see a flash of their global preference on page-load, before our JavaScript kicks in.

Wouldn’t it be nice to have a way for users to change their preference site-by-site, and have browsers remember their preference? That’s what the proposed Web Preferences API would do. This proposal gives us access to update a domain-specific setting for any prefers-* query, for any user, and have the browser remember that setting when they return.

That proposal has been underway for some time, but last month it was adopted by the CSS Working Group, and will be added to Media Queries Module Level 5.

Relaxed layout containment for size queries

Part of the reason for moving Container Queries out of the Containment spec is a drive to relax the relationship between these features. Containment is essential for making size queries possible – but the existing breakdown of containment types defined for the contain property is not a perfect match for what we need.

Our initial specification relied on applying size (or inline-size), layout, and style containment to all size-query containers.

All three of those are necessary precautions to avoid looping behavior, where changes inside a query could impact the results of the query. However, over time we’ve found that only some style and layout containments are strictly required. If we don’t need as many restrictions on a container, we should remove the ones that aren’t necessary.

Back in March we resolved that anchor names are not blocked by style or layout containment. I immediately opened an issue pointing out that this situation is not specific to anchor positioning, and we should consider allowing all positioned elements to escape layout containment – and therefore escape containers. Ian Kilpatrick (a Blink engineer) followed up by proposing we no longer apply full layout containment to query-containers, and only apply an independent formatting context.

Two weeks ago, presumably as a celebration of my birthday, the Working Group resolved to make this change.

Moving forward, that means it still won’t be possible to use subgrid across a container boundary, but it will be possible to do things like:

I hope we can continue to relax the impacts of containment on container queries over time. At this point, we might not see major changes to existing features – but we might find more situations like anchor position where a new feature should not strictly follow containment rules applied by query containers.

Querying partial feature support

There’s been a long-standing issue with how to handle @support queries for features that may be partly implemented in one or more browser. The most notable case was browsers extending the gap property from being grid-specific (2017) to being supported in flexbox as well.

Firefox implemented that change late in 2018, Chrome/Edge rolled it out in mid-2020, but Safari didn’t add flexbox gap support until early 2021. For several years, all the browsers were reporting support for the gap property, but only one browser had full support in all the relevant layout modes.

This is the result of an essential design principle of the @supports rule: browsers should not have to maintain a list of supported features. That’s been attempted in the past, but the lists would be to long to maintain well, and quickly get out of date. Instead, when a browser parser encounters the @supports rule, it tries to parse the contents of the query:

We can query for @supports (gap: 1em), and any browser that understands gap: 1em as a valid CSS declaration will claim support. But there’s no way to check that the declaration does what we want in all cases.

This situation has come up again recently, with browsers adding support for box alignment in block and absolute positioning contexts. As Michelle Barker mentions in her post:

One thing that concerns me, is that this seems to fall into that tricky area where it becomes impossible to test for browser support and provide fallbacks using a feature query – much like gap when it was implemented for flexbox. As align-content is well-supported for Grid and flexbox, the feature query doesn’t help us here.

Back in January, browsers agreed to maintain a short list of these situations, and provide named queries in specific cases. To make this work, it has to be a tool we resort to rarely, in a way that is coordinated across all the major browser engines.

The recent update here is that we’ve agreed on a syntax@supports named-feature(<keyword>) – and our first feature keyword: align-content-on-display-block. Once browsers implement this, you will be able to test:

@supports (align-content: center) {
  /* browsers that support align-content ANYWHERE */
}

@supports named-feature(align-content-on-display-block) {
  /* only browsers that support align-content in block layout */
}

If you skim through the minutes from our July meetings you will also find a number of updates related to the CSS ‘masonry’ proposals.

WebKit and Chrome have two competing visions for how masonry layout ought to work in CSS. WebKit wants masonry to be part of grid layout, and Chrome wants to keep them distinct. The former leads to grid properties that behave slightly different in different situations, while the latter means duplicating a number of properties that would otherwise be identical.

I don’t have strong feelings about this, or strong use-cases for masonry – but for a second there, it seemed like a hot debate. Both teams posted the competing proposals, people ran surveys on social media to get developer feedback, and then… nothing.

So what’s happening?

You might remember, a similar thing happened last year with two different proposals for anchor positioning. Rather than choosing one or the other, there was an attempt to merge the best of both. That took some time, but the resulting feature is much more powerful and usable than either of the initial proposals. The work paid off.

In this case, we can’t fully have it both ways. Masonry will either be part of grid layout, or it will have to be separate. But in many ways, we’re taking the same approach: Chrome is opening issues to show where their masonry might conflict with existing grid features, and WebKit is looking for ways to minimize those conflicts. Depending how those conflicts are resolved, we’ll have a much better sense if the masonry-in-grid approach is viable or not.

And then we will (hopefully) not be debating how the feature works, but only how it is ‘spelled’ in CSS syntax. Maybe kicking that can down the road will give us more information to work with.

Mia from behind,
standing at a laptop -
speaking to a conference audience
and gesturing to one side

Cascading Style Systems

A workshop on resilient & maintainable CSS

New CSS features are shipping at an unprecedented rate – cascade layers, container queries, the :has() selector, subgrid, nesting, and so much more. It’s a good time to step back and understand how these tools fit together in a declarative system – a resilient cascade of styles.

Register for the October workshop »

Recent Articles

  1. see all Article posts
  2. A stepped gradient of a pink hue in 2% lightness increments from 100% to 58%, labeled 'spec'
    Article post type

    CSS Working Group Updates for June & July

    What I’ve been working on as an Invited Expert

    The CSS Working Group has regular face-to-face meetings (hybrid online/in-person) throughout the year, and they always result in a flurry of activity! Here’s a rundown of some highlights from the last few months, with a focus on the features I maintain.

    see all Article posts
  3. A dog zooming by the camera, up-close, body twisted and eyes wide as it circles a grass yard
    Article post type

    Zoom, zoom, and zoom

    The three types of browser (and CSS!) magnification

    I’m working on an article about fluid typography, and relative units. But instead, I fell down this rabbit hole – or a cleverly-disguised trap? – trying to understand ‘zoom’ in the browser (not Zoom™️ the software). Since I couldn’t find any up-to-date articles on the subject, I thought I shoul…

    see all Article posts