This content originally appeared on Bram.us and was authored by Bramus!
Martin Winkler published a package that polyfills Element.matchContainer
to get notified in script when a Container Query matches/unmatches. Under the hood, it uses a StyleObserver
.
~
Window.matchMedia()
With Window.matchMedia()
you can observe whether a Media Query matches the given document.
const mql = window.matchMedia("(max-width: 600px)");
console.log(mql.matches); // true when the document is ≤ 600px
Furthermore you can use it to observe changes, by listening to the change
event on the returned MediaQueryList
object.
const mql = window.matchMedia("(max-width: 600px)");
mql.addEventListener("change", (e) => {
console.log(e.matches);
});
~
Element.matchContainer()
One of the open requests at the CSS Working Group is to have something similar to Window.matchMedia()
but then for Container Queries. One of the suggested solutions is to have something like Element.matchContainer()
.
Today, Martin Winkler published a package that polyfills exactly that: match-container
:
Element.matchContainer()
is to@container
whatWindow.matchMedia()
is to the@media
query CSS feature.
It allows you to do things like this:
const cql = $someElement.matchContainer("(width < 400px)");
cql.addEventListener("change", (e) => {
console.log(e.matches);
});
Or this:
const cql = $someElement.matchContainer("(style(--my-property: some-value))");
cql.addEventListener("change", (e) => {
console.log(e.matches);
});
Sweet!
~
StyleObserver
under the hood
Peeking under the hood, I see Martin uses my technique from @bramus/style-observer
: set up a transition on some custom properties and listen for their transitionrun
event. These custom properties automatically get registered and applied on the registered Container Query.
When
Element.matchContainer()
is called the polyfill inserts a corresponding@container
query into the CSSOM. The observed element is tethered to an attribute selector inside this query block by a correspondingdata-*
attribute, ensuring the target element is the only element matched by this selector. When the@container
query matches a prepared CSS custom property is set on the observed element. A style observer (heavily inspired by Bramus’ StyleObserver) finally triggers the callback in the script code.
For example, if you observe "(width < 400px)"
, this piece of CSS automatically gets injected into the page.
@property --container-query-observer-bae45330cd3d4e0e96b60d26b57009b5-1740410397140-0 {
syntax: "<custom-ident>";
inherits: false;
initial-value: --false;
}
@container (width < 400px) {
[data-container-query-observer-bae45330cd3d4e0e96b60d26b57009b5-1740410397140-0] {
--container-query-observer-bae45330cd3d4e0e96b60d26b57009b5-1740410397140-0: --true;
}
}
The attribute you see there is also auto-generated and gets attached to the observed element.
Note that match-container
only registers its internally used Custom Properties. When observing a <style-query>
you must still register the property you are observing yourself. See the section on Custom Properties from @bramus/style-observer
for details.
~
Demos
Here are two demos that use match-container
. The first one uses a size query and the second one a style query. Whenever the container query matches/unmatches, the log gets prepended with a new entry.
See the Pen
Element.matchContainer() demo by Bramus (@bramus)
on CodePen.
See the Pen
Element.matchContainer() demo – Style Query by Bramus (@bramus)
on CodePen.
‼️ Don’t forget that container queries query a parent Element, so you need to attach .matchContainer
on a child of the container (!).
Also don’t forget to apply container-type: inline-size
when doing .matchContainer(<size-query>)
or to register the custom property that you are observing when doing Element.matchContainer(<style-query>)
.
~
In Closing
It’s very nice to see that Martin got to leverage the technique from @bramus/style-observer
to solve this longstanding request. It confirms to me once again that we need a native StyleObserver
built into the Web Platform.
Get match-container
here:
match-container
on NPM →
match-container
Source Code (GitHub) →
~
🔥 Like what you see? Want to stay in the loop? Here's how:
This content originally appeared on Bram.us and was authored by Bramus!

Bramus! | Sciencx (2025-02-24T15:48:50+00:00) Solved by StyleObserver: Element.matchContainer(). Retrieved from https://www.scien.cx/2025/02/24/solved-by-styleobserver-element-matchcontainer/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.