Element-First
Much e-ink has been spilled in the debate between mobile-first
and desktop-first
approaches in responsive design. Thankfully in 2016 that battle is behind us, but before I get into the new way, let’s briefly explain what the old battle was about.
Even though the term didn’t become popular until five years ago, you could say that desktop-first thinking was the original approach to web design. Even though mobile devices were increasingly able to access some form of internet leading up the 2010, if you were serious about providing a good experience to these mobile users on their small screens, low bandwidth connections, and limited CSS support it often meant that you would maintain both a desktop and a mobile website, or at least a desktop and a mobile interface that accessed the same data. This is the way things were before 2010.
After the increasing popularity of smartphones, as well as enhanced support for web standards on mobile devices it became possible not just to build one website that both desktop and mobile users could access - but you could also tailor how that single interface displayed depending on how much room (screen size) the browser was able to take up. What mobile-first means is that when building your layout, you designed the layout for phones and tablets first, offering overrides from screens with larger widths. There’s no functional benefit to arranging your styles this way, but it really helped clarify priorities for designers by forcing them to deal with the biggest constraints in the layout first.
So now that all devices are being accounted for - why change our approach? Because no matter how you look at it, both desktop-first and mobile-first mindsets still prioritize the layout over the individual design elements that that layout is comprised of. With element-first thinking we deal with the modules inside the layout first, and then put self-responsive modules into a very simple layout. We never have to worry what happens if the layout is displayed 600px wide, or 3000px, because we know that each module within that layout will always adapt to display itself according to the responsive styles it has been given, and also how the user and web page interact after the page loads.
Element-first layouts aren’t static, they are born when the page loads and live and adapt as the user and application interact
Element-first design is the spirit of the Atomic design principle, but looks very different in practice than how most people implement Atomic using their mobile-first mindset. Instead of writing styles in advance for every conceivable situation a widget my find itself in, we are able to allow individual parts of the layout to adapt responsively when those elements require it.
It makes more sense to say: These are the styles for the menu when the menu has 300px wide, and these are the styles when the menu is more than 300px wide
than it does to say These styles are in case the menu shows up in a layout outside a wrapper where it has less than 300px space, here’s how the menu shows up in a layout inside a wrapper with less than 300px space, here’s how the menu shows up in a layout without a wrapper but with a sidebar with less than 300px, etc…
and then also defining all those different layout variations at every breakpoint you want to support as well.
You can see why people have turned toward conventions like BEM to try to help them manage the complexity, but we’ve clearly gotten to a breaking point where our layouts are breaking under the weight of all of the classes and attributes we’re adding to them. We feel the need to use pre-processors which can’t help us after the page loads to try to output enough CSS just in case
we need it, then we have to deal with tons of CSS and minify and compress that down so it’s small again.
Why not just take an element-first approach?
Let’s say you have some HTML like this:
<form>
<input placeholder=Search>
<input type=button value=Search>
</form>
Now let’s say the responsive behaviour you want could be explained like this in english:
Search box and button are side-by-side until they get too narrow, then both the input and the button should be stacked on top of each other and full-width.
In a desktop-first mindset you would write your CSS like this:
input {
width: 100%;
}
@media (max-width: 600px) {
input {
width: 50%;
float: left;
}
}
In a mobile-first mindset, you’re targeting the mobile view (stacked) first and adding support for the side-by-side view only if the screen has enough room:
input {
width: 100%;
}
@media (min-width: 600px) {
input {
width: 50%;
float: left;
}
}
With the first two examples, your @media
breakpoint was set to 600px
not because that’s how wide the inputs will be when they switch. The chances are that search form is probably inside at least one other parent element with margins and padding and so when the browser is 600px
width, those inputs might be somewhere around 550px
or 525px
wide in reality. So in a desktop-first and mobile-first mindset you’re always setting your breakpoints based on the layout and how the elements show up in it. With element-first you would just say: I don’t care how wide the browser may be, I know when my inputs get to be
Instead of using a 525-550px
wide that’s the sweet spot where I want them to stack.@media
query to swap that CSS by the browser’s dimensions, with element-first design you could attach your responsive conditions to the <form>
element and say something like:
input {
width: 100%;
}
@element form and (min-width: 525px) {
input {
width: 50%;
float: left;
}
}
The code is very very close to the other methods, but now you can toss this search form in a sidebar, you can make it full-width, you can use it in any template and no matter how wide the browser is, when the form itself doesn’t have enough room to display the inputs side-by-side it will adapt. Even if the browser is 1000px
wide at the time that the form is squished below 525px
where you’ve put it in your layout.
See the Pen Atomic design with Element Queries by Tommy Hodgins (@tomhodgins) on CodePen.
See the Pen Modals with Element Queries by Tommy Hodgins (@tomhodgins) on CodePen.