Open-source project
marcj/css-element-queries avatar
marcj/css-element-queries

css-element-queries: a 2019 polyfill that still explains container queries

GitHub describes it as CSS Element-Queries aka Container Queries. High-speed element dimension/media queries in valid css.. The repository metadata lists JavaScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

4,241 stars475 forksJavaScriptMIT

At a glance

What is it?
marcj/css-element-queries is an event-based polyfill that lets CSS selectors respond to an element's own size, not the viewport. It predates native container queries and remains a useful reference for how to build such a system, though its maintenance has stopped.
Who is it for?
Adopt css-element-queries if you need element-based responsive styling in a legacy browser environment (IE10+) and cannot use native container queries. Do not adopt it for new projects where native container queries are available, because the polyfill is unmaintained and has known limitations like no support for img elements.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Probably not. The repository last received commits 37 months ago, on September 28, 2023.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • marcj/css-element-queries4,241 ★ · -1
Star history
Repository2026-08-132026-10-21
marcj/css-element-queries4.2k4.2k

-1 Stars in the last 69 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What problem it solves and who it is for

css-element-queries solves a gap in CSS: media queries only react to the viewport size, not to the size of a specific container. A widget that looks good in a wide sidebar may break when placed in a narrow column, even though the viewport is unchanged. This polyfill lets CSS rules respond to an element's own dimensions, so a component can adapt to its parent's width or height. The intended audience is front-end developers who need component-level responsiveness in browsers that do not support native container queries, which includes IE10 and IE11. The project describes itself as a proof-of-concept, which sets expectations: it is a demonstration of a technique, not a maintained production library.

The mechanism: ResizeSensor and CSS attribute selectors

The core mechanism is an event-based ResizeSensor class, not a polling loop. The README stresses that other polyfills listen only on window.onresize, which misses layout changes from CSS animations, :hover, or DOM mutations. css-element-queries attaches a sensor to each element that has a matching rule in the parsed CSS. When that element's size changes, the sensor fires an event, and the polyfill updates a set of attributes on the element. The attributes are named min-width, max-width, min-height, and max-height, and they hold space-separated values that match the breakpoints you defined. CSS rules then use the ~= attribute selector, which matches a whole word in the attribute list. This design means the CSS stays valid, and you can use any selector you want, because the polyfill adds attributes to the element itself.

Setup and usage: real commands and config

To use the polyfill, you include two JavaScript files at the bottom of your page: src/ResizeSensor.js and src/ElementQueries.js. No initialization call is required for plain script tags, because the polyfill attaches to the DOMContentLoaded event. If you use a module loader, you must trigger it manually. The README gives this example: var ElementQueries = require('css-element-queries/src/ElementQueries'); then ElementQueries.listen(); to attach to DOMContentLoaded, or ElementQueries.init(); if you want to parse all CSS and attach sensors yourself. The README warns that init() should be called after the load event, because CSS files are not ready when DOMContentLoaded fires. In your CSS, you write rules like .widget-name[min-width~="400px"] h2 { font-size: 18px; }. The polyfill reads these rules, adds the min-width attribute to the .widget-name element, and updates it as the element resizes.

Where it fails: known limitations and the wrong use cases

The README lists several limitations that matter in practice. First, it does not work on img or other elements that cannot contain child elements, because the polyfill adds hidden elements inside the target. You must wrap such elements in a div. Second, it forces the target element to be positioned relative or absolute, because the sensor elements need a positioning context. This can break an existing layout that relies on static positioning. Third, local stylesheets over file:// do not work, so you cannot test a static HTML file directly from disk. Fourth, if you have a CSS animation on an element that also has element query rules, you must add the element-queries animation to that element's animation list, as in .widget-name { animation: 2sec my-animation, 1s element-queries; }. This is a workaround to detect new DOM elements. These constraints make the polyfill the wrong tool for image-only components, for layouts that depend on static positioning, or for offline demos.

Maintenance and upgrade cost

The repository's last push was November 2019, and the latest release is 1.2.2 from that same date. There have been no commits or releases since. The project is effectively unmaintained. This has direct consequences. If you adopt it, you take on the cost of fixing any browser bugs yourself, and you must verify that it still works with future browser updates. The MIT license gives you permission to fork and modify, but you will need to understand the internal ResizeSensor logic to do so. There is also a natural upgrade path: native container queries are now supported in modern browsers, so you can migrate away from the polyfill. The maintenance cost is not just the code itself; it is the ongoing need to test against new browser versions and to maintain the animation workaround for any animated elements.

Alternatives: native container queries and other polyfills

The most direct alternative is native CSS container queries, which are now implemented in current versions of Chrome, Firefox, and Safari. Native container queries use a different syntax, such as @container (min-width: 400px) { ... }, and they do not require JavaScript or attribute selectors. The approach is fundamentally different: the browser engine handles the size detection natively, so there is no need for a ResizeSensor or hidden child elements. Another alternative is a different polyfill that uses a different mechanism, such as a ResizeObserver-based approach, but the README does not name any. The key difference is that native container queries do not force the target element to be relative or absolute, and they work on img elements if you set a container-type on a parent. For new projects, native container queries are the clear choice; css-element-queries is only relevant for legacy browser support.

The verdict: a useful historical reference, a risky dependency

css-element-queries is a well-documented implementation of a clever idea. Its event-based design is genuinely different from the window.onresize polling used by earlier polyfills, and it handles layout changes beyond viewport resizes. For an engineer studying how element queries work, reading the source of ResizeSensor.js is instructive. For a production deployment in 2024, the lack of maintenance and the documented limitations make it a risky choice. The project is honest about what it does not support, which is more than many abandoned libraries offer. If you must support IE10 and IE11 and cannot use a native container query polyfill, this may still be the best option, but you should write tests for every layout change you rely on, and you should plan a migration path to native container queries as your browser support requirements change.

Editorial conclusion

Adopt css-element-queries if you need element-based responsive styling in a legacy browser environment (IE10+) and cannot use native container queries. Do not adopt it for new projects where native container queries are available, because the polyfill is unmaintained and has known limitations like no support for img elements. Before adopting, verify that your target elements can be wrapped in a div, that your stylesheets are served over http, and that you can add the element-queries animation workaround to any animated elements. Test the polyfill against your specific layout changes, especially CSS transitions and DOM mutations, to confirm the event-based detection works as documented.

Frequently asked questions

What is ~= in CSS?

It is the attribute selector operator, and this polyfill's element queries are written with it. The page shows rules selecting a container by a minimum-width attribute, and explains that the library adds attributes to the DOM element according to its actual dimensions, so you should always use that attribute selector, especially when an element has several rules.

What does css-element-queries do?

It is a polyfill adding element-based media query support, so styles can respond to the size of a container rather than the size of the window. The page describes it as a proof-of-concept, event-based implementation using valid CSS selector syntax, supporting minimum and maximum width and height.

What are the limitations of css-element-queries?

It does not work on images or other elements that cannot contain elements, and wrapping them in a div works. It adds hidden elements into the target element and forces that element to be relative or absolute, local stylesheets do not work over the file protocol, and an element with a CSS animation needs an extra animation step so new DOM elements are detected.

Is css-element-queries still maintained?

The last push on the default branch is dated 2023-09-28. The newest tagged release is 1.2.2 from 2019-11-22, while the package manifest declares 1.2.3. The repository is not archived, and the page still describes the project as a proof-of-concept.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/marcj-css-element-queries.svg)](https://hysenlabs.com/projects/marcj-css-element-queries)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/marcj-css-element-queries.svg)](https://hysenlabs.com/projects/marcj-css-element-queries)