How Designers at Niche Manage Hundreds of HTML/CSS Mockups

Nate Bridi
Building Niche
Published in
10 min readFeb 20, 2018

--

The Niche Design Team believes in designers who code — in fact, we’ve come to depend on it. For years now we’ve built mockups with HTML and CSS using a variety of custom scripts, templates, and utilities. Our system is built to maintain hundreds of mockups and optimized to rapidly prototype concepts in high fidelity. It’s improved our communications with the development team, made our process faster and more effective, and has enabled us to produce work that’s higher quality. I won’t make an exhaustive argument for why designers should code — that’s been well-argued elsewhere — but I will give some insight into how the small team of designers at Niche has found success managing a large and ever-growing catalog of HTML/CSS mockups.

One quick note: For this article, I’ll use the term mockup and prototype interchangeably. Prototypes are, after all, semi-functional mockups.

How We Got Here

We don’t make “redline” mockups anymore.

When Niche first transitioned to having a dedicated design team, we did what seemed obvious: creating static mockups in Photoshop or Illustrator for each screen size, complete with the traditional red line annotations for spacing and type sizes. This was tedious, frustrating and the resulting mockups required a lot of work and interpretation from the developer. This is the daily reality for many UI designers. We jumped from tool to tool to try to find a magic bullet — from UXPin and Balsamiq for wireframing to Framer and InVision for prototyping — but it always felt like we were learning a new system of abstractions one step removed from the real thing. Those abstractions made layout and component management easier, but they never represented responsive design fully and what was produced was still essentially a static mockup. We felt like going to code was the answer, but it came with a lot of questions about how we’d manage it day-to-day.

In fall of 2015 a confluence of forces helped us to take the plunge. We heard talks with strong arguments for fully-coded mockups from Brad Frost and Dave Rupert (and many others) at An Event Apart in Washington, D.C. Back at home there was growing frustration with the difficulties of interpreting the static mockups. Re-exporting dozens of static screenshot assets for the umpteenth time with a minor adjustment pushed us over the edge. It became clear that layers between us and the code weren’t worth it. We pushed aside hesitations, closed Photoshop, opened up our text editor, and haven’t looked back since. As of today, there are over 1,300 files in our Niche Design GitHub repository.

Our Approach and Mentality

We have three primary goals for how we build our mockups:

  • Move quickly
  • Have the flexibility to try a lot of ideas
  • Serve as a high-quality piece of documentation for our developers to reference

Everything the Design team builds should be in service of those goals. A modern website is a culmination of many small decisions, both creative and technical, and the more of those we can tackle up front means higher confidence that our solution is the best it can be.

In most cases the published product does not appear appreciably different from the mockup we passed to the developer. One of our aims, then, is for our HTML and CSS to follow best practices in terms of accessibility, performance, and company standards. Semantic markup, good naming and structure are all important. Because designer code serves as documentation, it helps inform what will ultimately be published to Niche.com. The developers may not be copy and pasting our code exactly, but it serves as a way of communicating our intentions. If our approach differs widely from that of the developers, it may indicate a misunderstanding and an opportunity for conversation. Real HTML and CSS is simply the most precise way to indicate the nitty-gritty details of a complex design. Responsive breakpoints, for example, are difficult to accurately portray in static formats. There’s no better way I’ve found to explain those vital details than to simply see the CSS.

Our JavaScript on the other hand, serves Design Team needs only. Flexibility and getting something working fast are what’s important in a prototype, so we’re free to violate best practices, write little one-off scripts, pollute the global namespace and all sorts of other things that make front-end developers cringe.

We try to avoid monolithic frameworks or anything that enforces a strict structure. We are thankfully spared the multitude of moving parts that make production coding difficult, since we’re not concerned about state management or any of other interaction problems that frameworks help solve. Most of our scripts boil down to replacing placeholders with templates. Are there times when a framework might make some things easier? Sure. But every minute spent trying to figure out why a React component’s state object isn’t updating when I expect it to is a minute not focusing on solving our real problems.

A more freeform approach also helps to prevent us from getting too precious about what we’ve made. If it was quick to make, it’s easy to delete when it’s no longer needed or isn’t working.

Simply put, our tools do what any tool should: make our work easier. Each script was written because a process became annoying, impractical, or slow.

How We Do It

Overview

The Niche Design team maintains what is essentially a parallel version of the website. Each page on Niche.com is represented in our mockups, but they differ in important ways. We don’t have to worry about page load time, routing, SEO, CDNs, or many of the other vital components of making a production website. Instead, we optimize for flexibility, legibility and speed of composition.

Our Environment

We try to keep our environment simple, without exotic build scripts or frameworks. One concession we make is for a CSS preprocessor, LESS, which is compiled to CSS with a Node package (autoless) that runs locally on our machines. The benefits of variables, nesting, and mixins make the slight complication worth it. Beyond that, we’re able to serve all of our mockup files directly from the native Apache server that ships with Mac OSX. The server doesn’t run scripts, but it does allow us to use Ajax, which is how we serve up the components of our mockups.

The Code

We make heavy use of custom tags and attributes. Simple in concept, but with three powerful benefits: it’s easy to identify these elements within a script, it makes the code somewhat self-documenting and easy to read, and it’s very easy to reuse and remix our components.

Custom placeholder tags (left) are compiled at the time of page load (center) and are fully rendered in the browser (right).

I’ll go over three examples of how we use custom elements and attributes to make our work easier, each progressively more elaborate.

Icons
A simple example are our SVG icons we use throughout the site. We keep them all in a central SVG file, identified with an id. Placing them in a mockup is as simple as using our custom <icon> element.

A custom <icon> element becomes an SVG when compiled in the browser.

It would be very annoying if we had to copy and paste all that code every time we wanted to use an icon—and it would also be difficult to know what it’s supposed to be. Even worse, if we wanted to update the design of the icon we’d have to find every place and swap it out.

Notes
Notes are not seen live on site, but are used for internal documentation. They can be added to any element with a note attribute.

A “note” attribute added to any element is turned into a toggle-able overlay.

Notes are indicated with an overlay, so they don’t interfere with the layout or design. They can also be toggled to hide them entirely, but remain one hotkey away. Notes even support Markdown formatting, so links can be added.

Profiles
This last example uses both custom tags and attributes and is the strategy taken to an extreme. Some context is required first.

Niche publishes profiles on many things: colleges, schools, and places just to start. Additionally, we have “expansion” pages with detailed information on particular aspects, like Admissions or Real Estate. All told, there are hundreds of types of pages. The Design Team can’t manually maintain mockups of all of those, but we do manage about 50. The content of these pages varies widely, but fortunately is presented in consistent ways.

We use a system of nesting templates for each piece of content within our profiles, so they can be defined entirely by data. There are dozens of these templates, but each has configurable properties that affect their display. So to summarize, we have dozens of templates with standardized configurations mixing and matching to create hundreds of types of pages.

Yikes. Lots to keep track of.

Early on, we coded each profile mockup manually, doing our best to make sure it was accurate. Each one was huge and the code was very difficult to scan. Even worse, because our templates are coded to be structured in verbose, but consistent, ways, they were very repetitive. Over time, even small changes became gradually more difficult to manage. We needed a lightweight solution to cut down on the copy-pasting and make it easier to understand the contents.

Each template is represented by a custom tag. The configurations and values of that template are set through an object passed in through an attribute:

When the mockup is rendered in the browser, the <profileheader> element is replaced by the full code of the template and the corresponding values are populated. This pattern is repeated hundreds of times down the page. This approach makes the code easy to scan and understand. Moving content around within the page becomes simple as easy-to-make errors, like how tags are nested, are significantly easier to avoid.

These examples illustrate different ways we use templates and attributes to make our work faster and easier. The respective code to make these examples work is not overly complex or long. It does just enough to work.

What We’ve Learned

Don’t get hung up on code issues

Code of any kind is easy to obsess over — it rewards attention to detail and is infinitely tweakable. Code is the medium we’re using because it’s the best tool for the job, but we’re designers first. We can’t let it become more important than our primary goal: designing an effective and beautiful website. We’re not the best-suited to figure out every browser quirk or bug and it’s ultimately not our responsibility to handle. This isn’t an excuse to be ignorant or to willfully ignore them. As with all things, it’s a balance. But if we’re banging our head off our keyboard because our checkbox component is broken in Safari again, it’s time to head to Slack to talk it over with real developers.

Work with devs to use the standards they define

At the end of the day, code belongs to the front-end developers. We’re playing in their world so we follow their rules when possible. We adopted the BEM CSS naming conventions to align with Niche’s front-end developers. They’ve also defined a variety of other standards and guidelines that we try to follow. Thankfully they are always just a chat away to talk over the finer details of naming and structure.

It will take time

Our switch to HTML/CSS mockups was not an overnight process. It took time to create every page. In our case, the switch was in conjunction with a re-platforming of the whole company, so our mockups grew together with the product as a whole. There were also a lot of false starts and missteps, and we’ve thrown away more lines of code than we’ve kept. We try to keep a mindset of constant change and not to guard ourselves from adopting new approaches. We’ve reached a state of relative maturity in how our mockups are assembled, but it can certainly take a while. For us, it was several months to get our feet under us, and close to a year to feel like the product was represented and our tooling was mature.

High-fidelity mockups can be misleading

Occasionally, the high fidelity of fully-coded mockups can be misleading. Everything about them seems real and when something doesn’t work (because it’s not actually implemented) it can cause confusion — and frustration — within your dev and QA teams. When the mockup becomes more functional, the goalposts can move somewhat, and it’s important to have clear notes or indicators — and good team communication — to alleviate this.

Hiring will probably be more difficult

Let’s be honest, many designers don’t know how to code, don’t want to, or have no experience with it. Two of those are fixable. When hiring UI designers at Niche, we prefer candidates that have some exposure to HTML and CSS, or are at least very enthusiastic about learning them fast. Because many of our solutions are custom, they also require training for new hires, but the goal is to design these solutions to be easy to use.

First and foremost, always keep in mind the primary goals of mockups: To move quickly, have the flexibility to try a lot of ideas, and to serve as documentation for your developers. Moving quickly means keeping your environment simple and lightweight. Flexibility comes with tools that make it easy to reuse components without much overhead — cutting away tedium to save your creative energy for the actual design problems. For mockups to serve as documentation, your final HTML/CSS must be legible and well-structured. Work with your development team to agree on coding standards.

Finally, start small and build as you go. You’ll be amazed how quickly your catalog will grow. Solve problems and inefficiencies as they arise and avoid the temptation to make your tools “perfect.” Enthusiasm, persistence, and a “can do” spirit have gotten us to the point where we are managing hundreds of mockups. Code makes this all possible. We’re able to produce high-quality work at scale without driving ourselves crazy because we’ve invested in building tools that make it manageable. And we’ll keep building as the product matures and expands.

Does this sound exciting to you? Maybe you should consider joining our team.

--

--