If you are building a web application, don’t expect the RWD you read about to be the RWD you will use. RWD is going to be about abstraction, code management, and using the right methodologies

A while back, when I was a frustrated architect leading a talented team of web application developers on several initiatives with multi-screen targets, I claimed that Responsive Web Design (RWD) is not the Holy Grail of write once/deploy everywhere.

So, what has changed since then?

Still frustrated. Still working on mobile/tablet/desktop projects. Still think RWD is chasing a dream.

Since those early days of RWD (back in May), a lot of things have changed. More libraries. More JQuery plug-ins. More people claiming the virtues of RWD. More carousel plug-ins. My god, how many carousel plug-ins do we legitimately need as an enlightened society?

I tried, I really really tried, for a recent customer to get my team to build a relatively simple web application using RWD design principles — media queries, plug-ins that handle some of the heavy lifting (Masonry is actually quite excellent).

Keep in mind that my team builds web applications for Fortune 500 companies in a variety of industries, primarily working on analytics applications and other business intelligence solutions. We are a small consultancy group with engineers that have, each, over 20 years of software development experience and considerable subject matter expertise. All of us self-taught hackers. All of us love researching new ways to do things and then using them — and, of course, on the customer’s dime. Don’t tell anyone.

I’m in charge, because I can talk to customers that aren’t tech-savvy. None of my other team members are in charge, because they can’t. We all play Quake, and I’m very good with the railgun.

The point is, we’re not beginners.

So we had a relatively simple (actually, extraordinarily simple) request from a publishing company — build an interactive web application for a customer of theirs that allows users to select categories of content and display products that match those categories. The app had to work offline on an iPad and an iPhone, and had to work on the desktop as well.

So — cool stuff. The product database was relatively small, a few hundred products. We decided to store them in a JSON format on the client, and check for updates when the client was on the network. Data storage: check. Offline caching: Check. Well, sort of check — the application cache is a prickly pear in and of itself, but that’s a different topic. Didn’t even need a database server to deliver the product catalog, the customer was anticipating only quarterly changes and were more than happy to fund us to support that in an engineering way.

On to the front-end. We had two different UI’s in mind, one for the iPhone, and one for the iPad and desktop. As an aside, we’ve been doing a lot of that recently — we use the iPad experience to inform the desktop, and our customers have been very pleased with the results.

So — two different UI’s. Shouldn’t be hard, right? Figure there has to be a good methodology for handling this, some good frameworks, a plug-in or two that’ll help us.

The was some marketing-type content that we had to put up front — an introduction to customer’s products, some instructional content, author information, and so on. We laid it out, threw Masonry at it, and voila — it looked… Pretty good. Okay! On to the app portion of the application.

At it’s most basic, the UI was sort of like the iPad email application. On the iPad, a pane on the left for the product categorizations, and the main pane showing product details with various information groups along the top arranged in tabs:

There are maybe 15 different attributes that a user could refine their product search with, so it fit easily into the left pane in a nice list, pretty list, and when you click on the items, they had a nice little effect that showed you that attribute was being used in the product filtering.

And as you tapped, basic product information for each of the products would appear in the main pane, with a little thumbnail of the product, the name of the product, and a brief description. If you tapped on a selected filter, the product list would gently fade and refresh with your new list.

A series of tabs along the top would also appear, categorizing product information into buckets. The first tab would default automatically, and tapping the tabs would show the different sets of information — instructional data, pricing, contact information, and so on — for each of the selected products.

So — we have CSS driving the layout and Javascript handling the various interactions. Perfect start.

Then one of the guys took the iPad and rotated it. Not so perfect.

So, we took step one of RWD. But the first challenge presented — we wanted to hide the left pane when the user was done filtering attributes so that we could show more product data on the screen. We introduced a swipe feature on that pane, so that the user could select multiple attributes and then, when done, swipe the pane almost completely off the screen, leaving a little bit available so that the user could swipe it back.

But we didn’t want this to happen on the landscape orientation. So, in JavaScript, our first IF/THEN. If iPad AND Portrait, then add this swipe event.

OK. No big deal so far. We also had to enable scrolling on the tab list, because there were too many tabs to fit in portrait mode. But that was OK, too — we could do that for the landscape orientation as well, so this was just a CSS change.

But the attribute pane looked weird. It only had the 15 items, and so half the pane was empty. Making the item selections taller made it look like we were simply trying to fill up space. So, enter our first CSS media query — set the height of the left pane based on whether we were iPad portrait-oriented or landscape-oriented. Make the left pane sort of hover over the main pane, at half the height of the screen in portrait mode:

OK, so we’ve got a minor JavaScript branch and a few CSS media queries. Not bad, but we’ve only handled the same device so far. And looking into the crystal ball, we started to sweat.

RWD is, as I’ve suggested, primarily geared towards brochure-style sites: sites that are geared primarily towards content delivery and not interactive application functionality. The experience on an iPad can’t simply be reformatted to work on an iPhone — the experience often has to be completely different.

On an iPad, relative to an iPhone, the information and experience hierarchy is flat. If you refer to the above images, particularly the landscape one, you’ll note that everything is on-screen, all at once — the filter attributes, the product lists, the tabs. This is even the case on the portrait version, with the user having the added ability to swipe the filters away — so a slight bump in the hierarchy, if you will.

The iPhone User Experience Hierarchy

On an iPhone, the experience hierarchy can be deep. You only need to look at the Settings app on an iPhone versus and iPad to see glaring examples of how deep you might have to go on an iPhone’s navigational hierarchy as opposed to on the iPad. Go ahead and try it.

So, there were a few challenges now from a UI perspective. We needed to plan the information hierarchy — we would go from a user selecting one or more filters, and then to a user selecting a desired product (since it was only feasible to show a single product on the screen at a time), and then to the product details, separated in some fashion by the data categories previously represented by tabs.


At this point, we seriously considered doing what we thought would be best, and what we’ve done in the past — abstract out the JavaScript and CSS that could be leveraged by both the iPad and iPhone versions of the UI — and then have form-factor-specific CSS and JavaScript files.

But we didn’t. I wanted to forge ahead and see if there wasn’t something to this RWD thing. Is it as easy as people make it out to be?

Spoiler: It ain’t. Maybe for an online brochure it is, or a news article. But not for a web application. At least, not one you’d be proud of deploying, or one that your customer is likely to accept.

So, the first step — the left pane of filter attributes becomes the first full screen of the web application, taking up all the real estate. We do a CSS media query to handle the positioning. Turns out that the 15 or so filter attributes that fit so nicely in the pane on the iPad don’t fit on the iPhone without scrolling.

Well, in for a penny, in for a pound. We decide to use an accordion for the filter attributes, and divide the attributes up into groups that would make sense to the user. These were the same group names that separated the attributes in the left pane of the iPad user experience, so we didn’t have to think too hard.

So, we did a JavaScript branch for the iPhone — adding an accordion. We had to also re-factor some of the attribute-selection/deselection code so that it worked properly in the accordion, and also add some additional ability to indicate to the user that at least one filter attribute from the accordion group was being used in the filter. We were able to leverage that code in the iPad version as well, but it took some time to re-factor that.

Because the goal of the filter screen was to allow the user to select one or more filters, we couldn’t just display the matching products until the user was done selecting filters. Also, the user was given positive feedback in the iPad experience: as they selected filters, the products matching their criteria would appear automatically. They knew that what they were selecting was resulting in matching products.

So, we decided to show a product count — how many products matched the criteria you were selecting — and then a button that would take you to the products that matched when you were done with your selections.

Okay. So, another JavaScript branch, draw the button, add the logic for doing a product count when a filter was clicked, update the button. Add the button to the CSS file. No need to do it in a media query, really — but we were thinking that we might have to make changes in the future, and we could group by media queries, so we put it in.

Just a couple more IF/THEN’s, a couple more media queries… And our code is starting to look… Complicated.

Now, before anyone says “why didn’t you use Sencha or JQuery Mobile” or any of those other frameworks that at least handle the paging that I’m describing above, it’s because of this: if I used either of those, the app would look the same on the iPhone and the iPad; just smaller on the former, and larger on the latter. We would’ve had the same issues forking in the accordions and laying out the pages. In short — no way it would’ve worked and provided the optimal, device-specific user experience that we wanted to deliver.

Back to the task at hand.

So we have page 1 working. Now we have to show a simple product list of products matching the criteria from the filtering. We already have code that derives the product list, but the product listing itself is much different from the main pane display on the iPad. Much.

So we IF/THEN in JavaScript again. We show a simple scrolling list of products, we tack on a “Back” button so the user can get back to the filters, and we create a new action handler on the product list that will take us to the third page, where we show the product details.

Another IF/THEN in JavaScript. More CSS specific to the iPhone that had no analogous entries for the iPad, adding it to the same file as the iPad CSS.

A Brief Aside

By the way — at this time, we were showing our progress to the customer. They were happy with the direction, but wanted to change some colors and things, some global to both user experiences, some to one or the other. Our fault for thinking this was going to be simple, so I had my team re-factor the CSS and use LESS, parameterize the various colors and gradients they wanted to change, and embedded them with the media queries. Fortunately, LESS supports @media with nested rules, so while we probably should’ve used it from the start, it helped us out as the customer iterated on the UI.


Back to the story.

So, we have page 2. It’s a page that didn’t have an analog in the iPad version, so was brand new. Everything related to it was in a JavaScript IF/THEN or CSS media queries.

More branches. More queries.

On to page three. This is a completely reformatted version of the main pane in the iPad application. Once again, we had too much data to show all at once, so we converted the tabs to an accordion, and put the product information in their appropriate accordion group.

Oh, and a back button to get back to the product list. And a “Start Over” button so the user could.

And I haven’t even mentioned all the transition effects and so on, all stuff that didn’t exist in the iPad version. All in CSS. And JavaScript. In those branches I keep referring to.

So now page 3 is working. The display is great, we’ve got the transitions down pat.

And, as you can imagine, the app looks nothing like the iPad version. It couldn’t be more distinct. And the customer loves it.

But our code was grotesque — a rats nest, a rabbit warren of branching logic throughout each of the front-end components. All using so-called RWD techniques and approaches espoused by people that know little to nothing about web application development and user experience. We considered it a failure. A relatively simple application, particularly when compared to the enterprise tools we’ve delivered in the past, would cost us double-time to support in the future. Unacceptable.

So, we re-factored again. We shifted all cross-screen JavaScript and CSS to their own files. Our single-page application index.html file referenced the appropriate, form-factor-specific JavaScript and CSS files during page load. We eliminated virtually all branches in JavaScript related to screen or orientation.

And all was good again.

We presented the final application to the customer for review. He held his iPhone and said the application looked great. As he put the iPhone down on the desk, he rotated his hand ever so slightly. By the time the iPhone had hit the desk, the web app was in landscape mode.

It did not look good. But we smiled, knowing that we’d already done the heavy lifting in our re-factoring and abstraction. So when he asked if we could support landscape on the iPhone, we said “Sure.”

What RWD Is

So that is what RWD is all about — good programming practices, not the expectation that one size fits all when it comes to a web page, not just an accumulation of responsive widgets, and sure as heck not as simple as everyone makes it out to be.

If you are building a web application, don’t expect the RWD you read about to be the RWD you will use. RWD is going to be about abstraction, code management (i.e.), and using the right methodologies. Not about a carousel.

I would really love to hear from anyone who has had similar experiences or differing opinions and approaches… We are also on the hunt for code organization tools that help specifically with this type of challenge. Submit your comments!