This post and idea were developed by Themeco's lead developers Kory Wakefield and Alexander Rohmann.
Much has been written about the humble media query. In the world of modern web development it is a necessary tool for most all projects, while being equally venerated (yay for responsive design!) and denounced (we need container queries!) at the same time. Media queries do a lot of things very well; however, they also inherently possess shortcomings that pose unique challenges, particularly when constructing tools for others to utilize in a site-building workflow.
When you're done reading, check out the interactive demo and GitHub repo at the bottom of this page.
Specificity vs. Abstraction
As developers, we like our abstractions. It's always helpful when we can tuck certain details away in a nice, orderly fashion somewhere else and not have to think about the specifics of each layer. With regards to media queries, there isn't a clean way to do this directly in our stylesheets as we don't have a dynamic layer to work with:
The code above will always fire when a device's viewport is at least
1000px wide. This is nice, it's predictable and works, but it is a rigid construct without any flexibility. What if there were some way to remove this specificity out of the stylesheet? Are there any inherent benefits to doing so?
This infers a similar result, but isn't tied to any precise figure. Wouldn't it be powerful to be able to change the meaning of what
.lg is expressing behind the scenes from one place? “But muh pre-processors!” I hear you saying. True, tools like Sass allow us to leverage the usefulness of variables and mixins throughout our projects and keep things relatively DRY, but you're still tied into a specific value. This abstraction could allow you to explore some of the following:
- Let's say for the most part you want
.lgto represent the same value on your site, but on certain pages you need it to break slightly higher or lower.
.lgcould represent different values on different pages, but all of your styles can be written in the same syntax throughout your website.
- If you have a design team that needs to create pages on the fly but doesn't have access to your development tooling, they can easily style elements as needed using classes like
.lg, and if you needed to change the value of what that represents down the road, you could do so without breaking their work or having a mixup of old and new values.
- If you create products for end-users to build out their own websites (e.g. WordPress themes, et cetera), providing your customers with a way to specify what
.lgis and how it works for their needs is a powerful concept. Furthermore, if a user wanted to jump in and make additional customizations beyond the options you provide, it would be a much simpler learning curve for non-technical users to understand our second example from above rather than the first.
While it certainly isn't the most difficult to understand once you get the hang of it, media query syntax can be a bit daunting for newcomers:
I remember having my fair share of moments in my early explorations of responsive design firing up the ol' Google Machine for a quick refresher on the computational incantations needed to achieve the ideas floating around in my head. Ah, how much simpler the following would have been to experiment with:
Not only that, but let us not forget that ever-important rule when designing for the web: every byte counts! As we all know, in this world nothing can be said to be certain, except death, taxes, and unwieldy stylesheets (Benjamin Franklin was a huge CSS nerd). As time goes on, teams grow, et cetera, unused and unnecessary styles inevitably creep into projects. Sometimes the blessing of pre-processors can also be a curse when left unchecked. You know that awesome mixin you're using to scatter breakpoints all throughout your stylesheet? It's spitting out that big mess of characters every time you use it, and in particularly large and complex projects, that adds up. Utilizing a smaller, more abstract syntax allows us to more easily ascertain what is going on with our styles and keeps file size to a minimum (even if handled poorly).
A Thought Experiment
The situations described above (along with a few others) are what prompted us to begin exploring and see if there might be some way to introduce more flexibility into our projects. Specifically for us, the possibility of providing our users with the ability to declare their site-wide breakpoints in one place and then utilize a much cleaner and approachable class-based syntax as needed was a powerful thought. It also meant that we would be able to style site layouts and functionality within a static stylesheet but allow the user to specify what the abstract values we'd be using meant.
- The script would need to be small and run early enough to output the dynamic responsive classes before our content is visible to avoid FOUC.
getComputedStyle! This gem of a function allows you to grab the CSS being applied to any element, at any given moment. Imagine you have this CSS:
Depending on your viewport width,
style.content will contain:
data attribute, allowing the breakpoints to be determined programmatically when needed.
This opens a new realm of possibilities. Without changing stylesheets themselves, we can change the ranges at which breakpoints trigger. Setting them in a
data attribute would allow them to be customized in the options of a theme or plugin.
It should be noted that Cubit is currently an experimental library. It has significant implications, but isn't battle tested. Can you break it? Do you see any potential issues with this particular method? Let us know in the comments, or get involved on the GitHub repo.
October 15, 2016 Update:
In response to some of the initial questions we've received please read the following.
- With this technique, the site could still degrade gracefully to any applied mobile first styling.
Regarding performance concerns:
- When used inline, there's no measurable speed difference that we can tell in our testing.
- Alternatively, it could load as one of the first script requests. This might bump your load time by 50-100ms on the very first load until the browser caches the file for future pages.
What's the tradeoff? Quick recap:
- Less code required in your stylesheets.
- Your breakpoints values can change at a site configuration level, without affecting the stylesheets. For example, the same stylesheet is loaded, but different site pages have slightly different/optimized breakpoint values.
As this is more of an experiment, there's still some discovery to go before we can decide if this is production worthy. It's looking promising, but our hope and goal here is that other developers with a grasp of responsive styling challenges will chime in with their thoughts and further testing. We also welcome contributions to our GitHub repo.
October 17th, 2016 Update:
It looks like others are working to solve similar problems in this space! Here are a few links that have been brought to our attention:
Cubit takes this
getComputedStyle innovation, packaging it up in a way that will swap any number of classes for you, which can correlate to any breakpoint you wish. We add an additional (and much needed) layer of dynamically generating the stylesheet holding the media queries. This allows for the breakpoints to be set at load, and altered in real time—creating a new dimension of flexibility.
Got anymore links for us? We'd love to know! Obviously this is a pain point that many are working to solve, and we'd love to see some more discussion come from this.