From Design to Code in 6 steps

Of all the contentious topics in the world of product design, none has interested me more than “Should Designers Code?” And while I would love to dedicate this blog post to debunking that very question as a false dichotomy, I’m instead going to walk you through my thought process for translating a design decision into code. Along the way, we’ll practice a few techniques, including:

  • Encapsulating our visual design choices as a UI component
  • Iterating over a real set of data to dynamically generate said component

We’ll be using a few tools of the trade, namely: Middleman (a Ruby-based static site generator) and Ace.css (A full-featured Basscss package for web apps).

I’ve listed the steps below, in stream-of-consciousness format. The final product looks something like this: http://design-to-code.cfapps.io/

Happy hacking! Please let me know if the steps below are exhaustive and accurate.

https://github.com/mattrothenberg/design-to-code


Step 1) Design the Component

Let’s say you have been tasked with redesigning the “card” component in your Twitter for Kittens web application. After exploring Dribbble for inspiration, you land on the following visual design.

Meow!

Step 2) Analyze the component

Take a look at the component and jot down the elements that are dynamic, or interchangeable from card to card. I’ve noted the following:

  • Avatar
  • Username (i.e., “@kittycat”)
  • Tweet Body (i.e., “You call this cat food?”)
  • List of Hashtags (i.e., “#catnip #kitties…)
  • Heart Icon (might have a different state when the card is “liked”)

These attributes will be tremendously helpful when we write the HTML for our UI component, and will inform the shape of the data set over which we will eventually iterate.

Step 3) Prepare the Middleman Project

Much like prototyping tools, static site generators are a dime-a-dozen. From my experience, Middleman has proven the easiest to set up and manage, and comes out of the box with some very handy features:

  • Sass & Compass support
  • A build-and-deploy pipeline
  • The Embedded Ruby (ERB) templating language
  • Access to the vast Ruby gem ecosystem

Head over to Middleman’s website and install per the instructions listed (If you have any trouble, feel free to reach out via the discussion below, or on Twitter.) Once you have installed the tool, run middleman init twitter-for-kittensto create a new project. You should be left with a directory structure that looks thusly:

twitter-for-kittens
├── Gemfile
├── Gemfile.lock
├── config.rb
├── config.ru
└── source
├── images
│ └── middleman-logo.svg
├── index.html.erb
├── javascripts
│ └── all.js
├── layouts
│ └── layout.erb
└── stylesheets
├── _normalize.scss
└── site.css.scss

In our layout.erb file, let’s pull in our dependencies via CDN.

<!-- Ace.css (Full-featured Basscss package for web apps) -->
<link href="https://unpkg.com/ace-css/css/ace.min.css" rel="stylesheet">
<!-- Material Design Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

Let’s also delete the boilerplate HTML inside of index.html.erb as well as the boilerplate SCSS in site.css.scss .

Step 4) Start Coding

While it is not in the scope of this article to teach the ins-and-outs of HTML/CSS, I would like to put forward the following strategy for translating a static design into code.

Mentally “slice” your component into discrete sections and identify patterns within them, as this will inform how you shape your HTML. In this instance, I’ve identified the following sections and patterns:

  • Card Body (with a Media Object inside)
  • Card Footer (with an inline list on the left, and a transparent or white button on the right)

For reference, many of these patterns are documented on the Basscss website.

And so, the markup for the card might look like:

<div class="card sm-col-8 md-col-7 lg-col-6 col-11 mx-auto border border-silver bg-white mb2">
<div class="card-body p2">
<div class="media-object clearfix">
<div class="avatar left mr2">
<img src="http://placekitten.com/g/80/80" alt="">
</div>
<div class="tweet overflow-hidden">
<h1 class="m0">@kittycat</h1>
<p class="h3 mt1 mb0">You call this cat food? lick the curtain just to be annoying. Run in circles. Purr while eating a nice warm laptop for me to sit on so kitten is playing with a dead mouse</p>
</div>
</div>
</div>
<div class="card-footer p2 flex items-center justify-between border-top border-silver">
<ul class="inline-list list-reset m0 gray">
<li class="inline-block mr1">#catnip</li>
<li class="inline-block mr1">#kitties</li>
<li class="inline-block">#mouse</li>
</ul>
<button class="bg-white border-none gray">
<i class="material-icons">favorite_border</i>
</button>
</div>
</div>

Let’s change the page background color to a light-gray by opening site.css.scss and adding the following style

body {
background: #f7f7f7;
padding: 25px;
}
So much style. Such little CSS.

Step 5) Encapsulation via Partials

As aforementioned, Middleman makes use of the ERB templating language. In so many words, we can embed Ruby code into our HTML in order to do magical things like:

  1. Render partial templates (a.k.a, a way of sharing content across pages to avoid code duplication)
  2. Iterate over a set of data (e.g., generate “cards” based on a list of real data from our application)

In our example, we have a card layout with several dynamic elements, including the tweet body, avatar image, and associated hashtags. And we’ve hardcoded a sample card in index.html.erb.

Now, let’s create a file called _card.html.erb inside of our source directory. And let’s cut/paste our hardcoded HTML from above into that file, resulting in a blank index.html.erb file.

Wherever there’s a hard-coded value (e.g., @kittycat, or “You call this cat food…”), we’re going to instead use ERB to tell Middleman: Hey! We’d like this value to be interpreted dynamically whenever the partial is rendered. And so, we get something like this:

<div class="card sm-col-8 md-col-7 lg-col-6 col-11 mx-auto border border-silver bg-white mb2">
<div class="card-body p2">
<div class="media-object clearfix">
<div class="avatar left mr2">
<img src="<%= avatar %>" alt="">
</div>
<div class="tweet overflow-hidden">
<h1 class="m0"><%= name %></h1>
<p class="h3 mt1 mb0"><%= tweet %></p>
</div>
</div>
</div>
<div class="card-footer p2 flex items-center justify-between border-top border-silver">
<ul class="inline-list list-reset m0 gray">
<% hashtags.each do |hashtag| %>
<li class="inline-block mr1"><%= hashtag %></li>
<% end %>

</ul>
<button class="bg-white border-none gray">
<i class="material-icons">favorite_border</i>
</button>
</div>
</div>

Which means whenever we choose to render this partial, we get to pass through — as variables — an avatar, a name, a tweet, and a list of hashtags.

So, inside of your empty index.html.erb write the following code.

<%= partial(:card, :locals => {
:name => '@kittycat',
:avatar => 'http://placekitten.com/g/80/80',
:tweet => 'You call this cat food? lick the curtain just to be annoying. Run in circles. Purr while eating a nice warm laptop for me to sit on so kitten is playing with a dead mouse',
:hashtags => ['#catnip', '#kitties', '#mouse']})
%>

Save, refresh, and pat yourself on the back for encapsulating your card component via a partial.

Uhh, it looks exactly the same, you ask? That’s the point.

There are many benefits to this approach. Reducing code duplication is an immediate and obvious one, but one that has deeper ramifications. With an encapsulated component, if we’d like to adjust a particular style or attribute (e.g., change the font size of the tweet body), we only have to tweak one line of code in one single file.

On a more meta level, this example illustrates how code offers a lovely convention for expressing the intent behind our design decisions: that is, by allowing us to abstract away our various design decisions and implementation details, and surfacing a name that is descriptive of the component we’ve built.

Step 6) Iteration

Here comes the fun part.

Earlier, I scribbled a list of the elements that were dynamic, or interchangeable from card to card. This exercise was helpful in identifying which values were to become variables in our partial template.

We can take this one step further by imagining for a brief moment that we’re building out a real web application, where we need to show a dynamic list of tweets on the page.


One approach to solving this problem might be to copy/paste the partial from right above, changing values where necessary. And that’s a totally valid solution. But I’d like to show you another way; one that leverages a fantastic Middleman feature: rendering a partial using data from an external source.

Kill the Middleman server by pressing Ctrl+C, and make a new directory called data at the root of your project (i.e., the same level as your project's source directory). Middleman allows us to create YAML or JSON files in this directory, and provides ERB magic for us to access the data in our templates. So, let’s scaffold out a YAML file called tweets.yml that represents a list of tweets.

- name: '@kittycat'
avatar: http://placekitten.com/g/80/80
tweet: You call this cat food? lick the curtain just to be annoying. Run in circles. Purr while eating a nice warm laptop for me to sit on so kitten is playing with a dead mouse
hashtags:
- '#catnip'
- '#kitties'
- '#mouse'
- name: '@scottishfold'
avatar: http://placekitten.com/g/80/80
tweet: Flop over. This human feeds me, i should be a god white cat sleeps on a black shirt but asdflkjaertvlkjasntvkjn (sits on keyboard)
hashtags:
- '#meow'
- '#computers'
- name: '@sirpointyears'
avatar: http://placekitten.com/g/80/80
tweet: Purr for no reason see owner, run in terror for friends are not food toy mouse squeak roll over. Cough furball run in circles
hashtags:
- '#notatiger'
- '#fuzzymcfuzz'

We can now use ERB to iterate over that list of tweets, rendering a partial “card” for each tweet within. Inside of index.html.erb , add the following code.

<% data.tweets.each do |tweet| %>
<%= partial(:card, :locals => {
:name => tweet.name,
:avatar => tweet.avatar,
:tweet => tweet.tweet,
:hashtags => tweet.hashtags })
%>
<% end %>

Note how we’ve completely abstracted away the implementation details of our card. For the end user — or perhaps the developer working on your project team — a card is quite simply a UI component that has a name, avatar, tweet, and hashtags.

Spin up the Middleman server one final time, and behold:

Sweet, glorious data!

I hope this tutorial has been helpful! I apologize for hand-waving away things like installing Middleman, or how my brain translated an image into 20+ lines of HTML. If you get stuck, or would like in-depth discussion of anything, please reach out!