Element queries provide styling opportunities specific to an element’s dimensions. You could consider them the holy grail of responsive web design, allowing authors to determine an element’s look and feel regardless on where it’s placed. If given ample space you may wish to provide a richer experience or if your element finds its way into a cramped sidebar perhaps you’d only show the bare essentials. Element queries give us a way to do this without tying into an overall site structure which makes them a perfect solution for widgets, complex layouts, style guide-based designs, or anything with lots of individual components.
Let’s look through this!
Overview of the Article Component
As seen in the example I’ve designed an Article component that works at three different sizes (we’ll call them states):
- A small, list item-like state with only a title and timestamp.
- A medium sized state based on the list state from #1, but with a photo for added context.
- A featured state, complete with large photo, larger title, full attribution, abstract, and read more call-to-action.
For demo purposes, I’ve put the basic Article component HTML into different sized columns, allowing you to see each state. Resizing your browser or editing a column’s width in your browser’s developer tools will trigger layout changes (which is separate CSS), resulting in a visual change to a few Article components.
You can imagine this Article component being used throughout a news website or packaged as a syndication widget. It’s a pattern found CNN.com, which just so happens to be using element queries!
How It’s Built
Since element queries aren’t part of any specification (yet) we’ll need some help getting the functionality we want. I recommend eq.js by Sam Richards, a lightweight polyfill, though most of the other solutions work similarly. With eq.js you’ll only need to include one file:
Like other element query options, eq.js uses attributes to connect style changes to components. A basic structure for our example looks like this:
Similar to mobile-first design patterns, we are specifying our smallest size and then overriding styles as we have more space, except we’re using attribute selectors instead of media queries.
The Article component has different sizes for the title and photo for example (the CSS is lengthy to show here, be sure to view the CSS). In some cases, like the smaller sizes, we have no room for the abstract so we hide it altogether.
eq.js will parse our DOM and apply a
data-eq-state attribute with the appropriate values when the
DOMContentLoaded event triggers. Our largest state will have a
data-eq-state value of
article--medium article-large, while the middle state will only have
article--medium. Here’s how it looks when it runs:
It’s worth noting that if you’re willing to take a slight (almost negligible) performance hit when rendering you can move configuration to a Sass file. eq.js provides some tools for this. Here’s how they might look when applied to our example:
eq.js will pass your size map to a
:before pseudo element that results in something like this, which it can read and use to apply the appropriate attributes:
Implementation is pretty simple, but with all polyfills and experimental methods there are some gotchas:
- You can hit some circluar issues, but like anything else you’ll hit issues if you’re reckless.
These issues aside, I’m positive if you start developing this way you’ll find it difficult to go back. Element queries, or some future native implementation of them, really are an ideal way to build a truly flexible modular design. Hopefully we’ll have native support soon but until then we have excellent options via polyfills.