Menu Search
Jump to the content X X

Today, too many websites are still inaccessible. In our new book Inclusive Design Patterns, we explore how to craft flexible front-end design patterns and make future-proof and accessible interfaces without extra effort. Hardcover, 312 pages. Get the book now →

Media Queries Are Not The Answer: Element Query Polyfill

Responsive Web design has transformed how websites are designed and built. It has inspired us to think beyond device classifications and to use media queries to adapt a layout to the browser’s viewport size. This, however, deviates from the hierarchical structure of CSS and characterizes elements relative to the viewport, instead of to their container.

Extensive use of media queries might be the answer for today, but it is not a viable long-term solution. Media queries do not allow for reusable modules that adapt based on their containers’ size.

What Is Responsive Web Design? Link

Responsive Web design is not limited to a set of technologies; rather, it is a different approach to designing and building websites. I, like many, took Ethan’s words1 about responsive Web design too literally and overlooked the essence of what was being said:

“Fluid grids, flexible images, and media queries are the three technical ingredients for responsive web design, but it also requires a different way of thinking.”

We have accomplished great things while embracing the stated “technical ingredients” for responsive Web design, but we have much room for growth when it comes to a “different way of thinking.” Thinking differently should affect not only how we design and build our websites, but also how we design and build the tools and technologies that our websites are founded on.

Modular Design Link

When I learned about how media queries could be used in responsive Web design, I was excited by the possibilities. However, it was not long before I learned of the limitations. Media queries are great for adapting layouts to various screen sizes, but terrible for creating modular designs2. Modular CSS is already hard enough, and media queries provide very little to no help. Truly modular layouts need to respond to the sizes of containers, not just to the viewport’s size. Media queries, however, are based on the viewport, rather than an element’s container. There is some hope for standard CSS on the horizon, in the form of a W3C working draft3, by allowing the cascade inheritance to be broken and resetting an element to its defaults. But what about media queries?

The @media Hack Link

Web developers are masters at taking something created for one purpose and using it to accomplish other things. The Web’s history is littered with examples of this, and media queries are no exception. Kudos to Ian Storm Taylor for writing down his thoughts in the article “Media Queries Are a Hack4.” Hacks are necessary on the Web to provide desired functionality until proper support is achieved, as well as to provide support to older browsers. The W3C states5, “By using media queries, presentations can be tailored to a specific range of output devices without changing the content itself.” The key word here is “can,” but just because you can do something, doesn’t mean you should… But do we have any other choice?

The Element Query Link

Introducing the element query. An element query is similar to a media query in that, if a condition is met, some CSS will be applied. Element query conditions (such as min-width, max-width, min-height and max-height) are based on elements, instead of the browser. Unfortunately, CSS doesn’t yet support element queries, but that shouldn’t stop us from dreaming, hacking and pushing for new standards.

Conceptual Example Link

Consider the following example, in which the navigation menu should become visible when it reaches a minimum width of 500 pixels (representing one of many potential syntaxes):

nav (min-width: 500px) {
    display: block;

Compare this to a media query in which the navigation menu’s visibility depends on the viewport’s width and needs to account for the padding and other declarations of parent elements:

@media all and (min-width: 520px) {
    nav {
        display: block;

Now imagine having to build a modular component that needs to be placed in containers of various sizes on a single page. One current approach is to provide different theme classes (like .module--large) to trigger CSS in media queries. This, however, adds a lot of complications and requires a module to know how its parent will react to various viewport widths.

Issues: Invalid and Looping Conditions Link

There are several cases in which the CSS of an element query would invalidate the element query itself or create recursion. Hopefully, the browser would be able to detect these conditions and respond appropriately.

Consider the following examples.

Once an element reaches 500 pixels wide, it’s resized to 200 pixels, at which point the rule would no longer apply:

.element (min-width: 500px) {
    width: 200px;

Once an element’s width reaches 31.250 ems, its font size would be decreased, which changes the definition of the em unit:

.element (min-width: 31.250em) {
    font-size: 0.75em;

Once a container’s width reaches 450 pixels, the size of its child changes to 400 pixels, which would shrink the size of the container:

.container { float: left; }
.child { width: 500px; }
.container (min-width: 450px) > .child {
    width: 400px;

There are many other such examples, but you get the point: Element queries are not as simple as we had hoped.

Element Query Polyfill Link

Element queries seem pretty awesome, but they also have some real issues. To help sort these out, I’ve written a proof-of-concept polyfill. The polyfill has enabled me to understand how a browser might react to various conditions. As I got further along, I realized that the polyfill could hold real value in the Web community’s debate on element queries, and that some developers could even start using element queries today.

The elementQuery polyfill script is available on GitHub6 for you to use, fork and contribute to.

Selector Syntax Link

The syntax used in the previous examples caused limitations, so I updated the polyfill to support an attribute selector syntax. The ~= attribute selector7 checks whether the value is contained in a space-delimited list (supported in modern browsers above Internet Explorer 6).

The following examples show CSS rules using the syntax required for the elementQuery polyfill.

This rule queries itself for a single condition:

header[min-width~="500px"] {
    background-color: #eee;

This rule queries itself for multiple conditions:

header[min-width~="500px"][max-width~="800px"] {
    background-color: #eee;

This rule queries a parent for a condition:

header[min-width~="31.250em"] nav {
    clear: both;

How It Works Link

Unfortunately, the elementQuery polyfill requires JavaScript and the Sizzle8 selector engine (which is embedded in jQuery). When the document object model (DOM) is ready, elementQuery scans the document.styleSheets collection for any CSS rules that use elementQuery. When it finds a match, it extracts the following information:

  • Selector
    Such as header, ul > li.class
  • Query type
    min-width, max-width, min-height, max-height
  • Query value
    Such as 500px, 31.250em

elementQuery then uses this information to add or remove attributes from elements that match the given selector and query condition.

Expanded Support Link

Most browsers, but not Internet Explorer, don’t provide access to the contents of cross-domain style sheets, which causes issues when CSS files are served from a content delivery network. Additionally, parsing style sheets takes time (not much, though). So, I created two branches for elementQuery: master9 and prod10. The master branch includes the code for extracting the necessary elementQuery information (selector, query type, query value), and it also provides a selectors() function to export the information. The prod branch requires the information to be declared in JavaScript, which avoids the cross-domain file issue and the time required to parse the style sheets.

Here is an example of how to export elementQuery information using the master branch:


And here is an example of how to import elementQuery information using the prod branch:


Working Examples Link

I’ve put together a few working examples on CodePen (using the master branch) that you can experiment with or fork. I would love to see what other examples people create (which will probably be much cooler than mine). Just be sure to tag them with #elementquery11 so that others can benefit.

Be Creative Link

I didn’t write this just to get you to jump on the element query bandwagon, but rather to encourage people to think about how we can solve the problems that are limiting our medium. Let’s keep the discussion going and make the Web a better place. So, go wild and make cool stuff!

Further Reading Link

(Source of image on front page: Looking Beyond Common Media Query Breakpoints19)


Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19

↑ Back to top Tweet itShare on Facebook


Tyson Matanich is the lead developer on the home page. His writings reflect his own opinions and don’t necessarily represent Microsoft’s. He focusses on frontend Web development but will do what’s necessary to get the job done. You can follow him on Twitter or read his blog.

  1. 1

    I have been reading about CSS FLEXIBLE BOX OR “FLEXBOX” It will be interesting if that concept picks up more traction and see if it plays out.

  2. 2

    Tyson Matanich

    June 25, 2013 7:39 am

    Also, if you want cleaner rules you can use a CSS preprocessor to nest your selectors:
    header[min-width~="31.250em"] {
    h1 {
    font-size: 1.75em;
    nav {
    clear: both;

    • 3

      Alexandru Lighezan

      November 6, 2013 4:55 pm

      I was wondering wether inside the css element query you could add a class. That class could have properties defined somewhere else in the css. Your js script could then add that class to the element based on its size. Should be much faster than reading all the rules and applying them to the element.

  3. 4

    It seems the repo has gone missing (404).

  4. 6

    Joshua Smith

    June 25, 2013 10:32 am

    Responsive design is dying for a solution to this. Yours it a wonderful step in the right direction.

    There are still a few hurdles that we need to solve. For instance, if classNames are dynamically added, which otherwise would have triggered these element-specific styles on DOM load or resize, then there’s no listener that can trigger a refresh.

    Additionally, if we set the “width” or other attribute of an element dynamically, then these element-specific media queries won’t trigger a rerender.

    I love that we can begin considering flexible designs at the element-level, but a fully-developed solution must accomodate these use-cases and others like it.

    Waiting with bated breath :)

  5. 7

    Explain: what does “access to the contents of cross-domain style sheets” mean?

  6. 10

    Marc Schmidt

    June 25, 2013 11:52 am

    Another css element query alternative that supports more events than windows’s ‘resize’ event.

  7. 11

    Sebastian Otto

    June 25, 2013 3:19 am

    I wrote something similar 3 Months ago but your syntax is definitely better –

  8. 13

    This method is nice but it cost perfromance, especially on mobile devices. Manipulating DOMElements is resource consuming.

    • 14

      Thomas Dobber

      November 7, 2013 5:28 am

      It would be a good idea to write mobile first css and, once you’re done, use something like enquirejs to load the script once the screen width is close to your smallest min-width element-query.

  9. 15

    Ethan Hackett

    June 25, 2013 4:48 am

    Excellent element queries will be incredibly beneficial for the plugin market. Responsive plugins aren’t enough. I find users often put plugins in the strangest of places….

    • 16

      Jon Hobbs-Smith

      June 25, 2013 4:53 am

      Indeed, if you don’t even know what layout your component is going to end up in… This could be very useful in tandem with Web Components.

  10. 17

    Jon Hobbs-Smith

    June 25, 2013 4:48 am

    Responsive Design is crying out for this. I really hope browser manufacturers and the W3C can band their heads together and come up with a solution. The simple thing would be to not allow any recursion, or not allow inner elements to affect the size of the container, like iframes do.

  11. 18

    Vitaly Friedman

    June 25, 2013 5:15 am

    You can also follow a fantastic discussion about the so-called “element media queries” in a recent Scott Jehl’s article on the Filament’s group blog: Working around a lack of element queries.

  12. 19


    June 25, 2013 5:15 am

    jQuery required? I really wish that this solution was native. As I would like to use this technique on navigation elements.

    • 20

      Tyson Matanich

      June 25, 2013 7:29 am

      It heavily relies on Sizzle to quickly query for elements matching the CSS selectors. Doing a standalone script would require me to rewrite most of Sizzle. Hopefully browsers will eventually start supporting element queries so we wouldn’t have to rely on JavaScript.

      • 21

        Nobody forces you to use Sizzle. There are a few faster selector engines around – I’d just take one of those, add the core script of headJS or anything else that does help us to some nice on-DOM-ready call, add the rest of the actual polyfill on top – and taadaa! Bill’s your uncle.

        cu, w0lf.

        ps: Yep, I actually did that already a few times in other cases. Native JS is just so much more fun .. ;)

        pps: Dear Smashing Magazine: Yeah, I’m STILL no spam bot. Instead you folks obviously STILL haven’t got your “anti-spam” issues fixed.

  13. 23

    James Faulkner

    June 25, 2013 5:57 am

    Thanks, Tyson for sharing your tips & knowledge about the element query as well as showing us some working examples and pointing out some of its issues.

  14. 24

    Dom Washburn

    June 25, 2013 3:20 pm

    If we’re pushing for standards I’d ask we go a step further and examine how we’re defining these “break points” and re think the ambiguous terminology that is min and max width… yes we’re used to it, but as much as @media is a hack so is this.

    I would propose that we use less-than, greater-than, equal-to, between, range … etc.

  15. 25

    Adrian Zumbrunnen

    June 25, 2013 6:53 am

    You can actually use a wrapper which i functions as a module.

    for instance:

    if you use box-sizing border-box im combination with the surrounding element (‘module’) which dictates the width, you get a pretty modular result.

    you start sketching your modules first, then the contents within will adapt just smoothly.

  16. 26

    Daniel Montgomery

    June 25, 2013 8:21 am

    This is a great overview of the topic and good examples.

    I feel the main bottleneck will be surrounding the recursion examples provided. To me, this speaks more for the current model where elements can be sized from containers or contents. I don’t know how the browser decides what to do when there are conflicts, but building from the inside out and the outside in is going to present tons of challenges.

    It feels to me like websites used to build for wrappers fitting to their contents where now almost all content is meant to fit inside their wrapper.

    Could a new element type or procedure be used to force contents to fit inside rather than bloat the wrapper? It’s also an issue of using a structural and style system (CSS) on top of a system (HTML) that is supposed to be abstracted from the structure. They are supposed to be independent, but that’s not realistic at this point.

    If we can’t even get a flexible box model supported I don’t know how long before something useful like this will exist. Here’s hoping soon!

  17. 27

    The more we use Media Queries, the more problems we start to see arrising. This kind of solution would definatly help us to solve a few of those problems. Maybe a CSS4 implimentation (if they can get off their ass).

    • 28

      Šime Vidas

      June 26, 2013 2:46 pm

      You’re welcome to write a proposed draft specification for element queries.

  18. 29

    Chris Howard

    June 26, 2013 10:37 pm

    This is a great solution to one of the RWD problems. However, it is still OSFA in nature.

    By gratuitously pursuing OSFA RWD, we are placing limits that never allow us to take full advantage of the medium. The smartphone, the tablet, the desktop/laptop all need to be seen as unique mediums with unique advantages, benefits and limitations.

    Developers of phone, tablet and desktop apps don’t simply rescale their apps for each device. Why do we do it with web pages?

    RWD should be constrained to the medium. e.g. on the smartphone medium, delivering normal graphics on an iPhone 3GS, and retina graphics on an iPhone 5. Or on the desktop/laptop medium, two column body layout on a desktop greater than 1680, and one column on less than that.

    But when we try transforming a smartphone, 320px wide layout, into a 1920 desktop, we make sacrifices on both mediums.

    If we must pursue OSFA RWD, then this proposal of element queries is better than media queries.

  19. 30

    So if the CSS spec. and browsers someday support the “element query” would this then eliminate the need to use something like ‘sizzle’?

  20. 31

    Wouldn’t a solution to the looping problem be fixed by using container queries rather than element queries? You’d still largely have the same functionality.

    I imagine it would work something like this:

    @parent (min-width: 500px) {
    .foo {
    width: 200px;

    In fact, now that I look at this I think it may be more useful. Allowing you to reuse a `@parent` query for multiple modules.


    looping may still occur if the parent elements width depends on it’s content. Although that is an issue with the element query too, so this is at least closer. In fact it could probably solved by only applying to elements that are positioned in a way that doesn’t depend on content.


↑ Back to top