AnyPerk’s Responsive Overhaul with Bourbon and Neat

Kevin Ko
AnyPerk Product & Engineering
6 min readOct 2, 2014

--

The AnyPerk birth narrative is amusing enough to warrant its own post; AnyPerk began primarily as a hustle company, and not necessarily a tech company. When I joined in October 2013 as one of three primarily back-end engineers, I inherited a nascent code base that never had the luxury to make thoughtful front-end architectural decisions.

In early 2014, we had the opportunity to set the tone moving forward when we were tasked with converting the entire site to become responsive. The mobile web experience on anyperk.com suffered directly from a non-responsive layout, which hurt one of our major KPIs, perk redemptions.

Unfortunately it wasn’t just a matter of waving a magic wand to make our site responsive, but there were many things to consider.

Problems

  1. Our legacy SASS architecture came in this form: Bootstrap and a file to contain all styles we wanted to “override”. This file was exactly 3198 lines long.
  2. Due to the source code’s dependency on Bootstrap, we couldn’t toy with another framework, Foundation because there were conflicts in class naming (such as “row”). This meant that unless we resorted to some messy hackery, we would have to try and strip out Bootstrap before implementing Foundation.
  3. If we went the route of Foundation, after following step 2, we would then have to redesign the site as one massive push, because a post-bootstrap code base meant no pages would be styled correctly. Instead, we wanted a solution that would allow us to push responsive pages one-by-one.

Coupled with the notion that it’s entirely possible that Foundation would just be another proxy for the problems we encountered with Bootstrap, we looked for an alternative: One that would let us write CSS the way we wanted, push iteratively, and allow for sane front-end architecture moving forward.

Solution

Long story short, we settled on thoughtbot’s Bourbon and Neat libraries. Bourbon is a lightweight mixin library, and Neat is an extension of Bourbon that provides a grid system. This decision provided the benefits we were looking for initially, and then some:

Separation of concerns, no Bootstrap conflicts

Both Bootstrap and Foundation suggest ways on how you should write your HTML by inherently providing CSS selectors on class names like “row”, “span*”, “hide-for-small-only”. Your HTML should not be concerned with how the presentation of your content will look, just as your CSS should not be concerned with the content it is presenting.

That Bourbon wasn’t a full-on framework allowed itself to extend onto our current Bootstrap framework without any issues. This also meant we could push responsive pages iteratively without affecting the Bootstrap-powered layouts for other pages.

So instead of writing Haml views that look like:

.row
.span9.main
%h1 Hello World
.span3.sidebar
%aside
.span6.main-content
%section

We could instead write:

.main
%h1 Hello World
%aside.sidebar
%section.main-content

Then we can adjust the grid columns, e.g. 3 for the sidebar, 6 for the content, in the stylesheets, where presentation logic belongs. This is especially important in the context of responsive, where a div class spanning 6 columns in the default view may actually be all (12) columns on a phone, or even no columns at all. A div class named “span6" quickly gets misleading in the context of multiple form factors.

Stylesheet Organization

While overriding CSS in the old Bootstrap days was simple (“Ah, I’ll simply add a bigger margin to this div here”), it lent itself to just piling code into one file, with no policing on what if that file inevitably became very large. CSS in a Bourbon world is more involved and thorough, as you need to ensure rules are written if you intend to do something wholly different in a different form factor. With that in mind, the next step was to write our CSS not in a single, monolithic file, but in directories that made sense.

For us, it was our Rails controllers — if the view being worked on existed in the Users controller, the any custom CSS for that page should belong in a path similar to app/assets/stylesheets/users/show.css.scss. There are no hard rules here, each organization has their own directory structure.

Execution

Start with the header (and footer)

Since navigation primarily exists in the header at AnyPerk, especially for smaller windows, the first thing to get right was the header. We created a new header partial and would dynamically call it if the page was intended to be a responsive page. We included the viewport declaration in here, too, because non-responsive pages with the viewport set would turn out horrific.

Use temporary class names in case of conflict with existing CSS

Because removing Bootstrap was the final goal, we wanted to make sure we weren’t using class names that were currently referenced by any of the legacy CSS. We added an “rr-” prefix (for “Responsive Redesign”) to our class names in the view, confident that anything with the rr- tag would not have already been referenced in bootstrap, and we could reference it in the new stylesheets safely.

Completely rewrite the views and any used mixins

We needed to get rid of the anachronistic “row” and “span*” classes that littered our views. Since this task also involved redesigning entire pages, we just went with a scorched earth strategy of completely re-writing the view in many cases. This was relieving, as it gave us an opportunity to start from scratch and write views that were more forward-thinking, rather than wrestle with legacy code.

We also wanted to stop using any Bootstrap mixins. The main mixin we used was btn, so we ended up re-designing the default AnyPerk button and implementing our own mixin.

Deploy page-by-page

After creating a responsive version of the header and footer, the first page to get an entirely responsive treatment was our main Perk page. Likely no one was around to appreciate the change, because it involved logging in through a series of non-responsive pages, but internally we could mess around with it, debug anything that came up, and proceed accordingly. Repeat until complete.

Once complete, remove all the legacy and temporary junk.

Once the entire code base was completely migrated to responsive (this took about 2–4 months, depending on your definition of “completely”), we removed Bootstrap and its mixins, as well as the old stylesheets once we were certain they didn’t hold any influence on the current code base. Once that complete, we removed all the “rr-” tags such that a div with the class “rr-page-container” ended up just becoming regular old “page-container”. The CSS follows suit.

Happiness

While the code base wasn’t immeasurably large, AnyPerk is a SaaS startup that had then been around for 2 years, so I estimate the amount of pages we had was pretty significant. Even then, the bulk of the migration took 2 engineers about 2 months, which included outright redesigning many pages, and many pull requests left in limbo due to a lack review time relative to the frequency at which pull requests were being made.

It became a pretty robotic process mid-way through the process, but fun in that it presented a massive improvement to not just our usability, but also our code base. Very few things broke, and they were patched easily when they did. Overall the process was smooth, and undoubtedly it was thanks to some sharp foresight in understanding specifically what we wanted and how we were going to execute.

Special Thanks

Lisa Sy at thoughtbot for convincing us to use Neat and the frame of mind to develop our front-end moving forward.

AnyPerkers directly involved in the project: Drew Dillon (PM), Sunny Tsang (Designer), Fumie Toyooka (Engineer)

--

--