Using Sketch and Framer to Create Responsive Mobile Prototypes for Remote Testing: Part 1

I have found that prototypes solve 99% of design problems. Whether reviewed with other designers, guerrilla tested on coworkers with limited knowledge of the project, or tested with users, if there is a problem in the design it will show up when prototyped. Framer is my prototyping tool of choice, for multiple reasons, the main reason being the ability to build prototypes that feel as close to a native application as possible. If you are new to Framer, learn more by checking out their website or download the free trial, as this post is rather technical.

My team does most of our user-testing with remote users on UserTesting.com. Many of our core customers primarily use our products within a desktop browser, but when trying to build and share “native feeling” mobile prototypes, members of my team ran into various problems.

I previously constructed an example workflow for desktop browser prototypes that worked well but did not translate to mobile. To maintain that Framer was still a viable rapid prototyping tool for multiple platforms with my team and the rest of the product team, I had to come up with a workflow that solved the issues my team was experiencing. The success criteria I established for this workflow was the ability to reuse some code from the desktop prototypes, be responsive across multiple mobile devices, solve the problems my team has been experiencing, and have a gentle learning curve for those with little to no coding experience.

Problem 1: Testing in Multiple Resolutions.

Designing in 1x resolution is a best practice — there are a lot of posts that outline the benefits, here is one. Framer renders prototypes in their native resolution, for iPhone 7 that’s 2x, iPhone 7+ 3x, and Android is all over the place with the vast amount of models in circulation. Designers on my team would have to make Sketch files and prototypes in multiple resolutions for multiple devices, or only test with users that possess a certain device.

iPhone Resolution Chart from PaintCode

Problem 2: Native Nuances

My team was having problems creating the little nuances that make a prototype feel native with multiple screen flows. Some of the questions I received on the matter: “how do you make the status bar seem static?”, “can you make a keyboard that works across multiple devices?”, “can you hide the gray background for overlays?”

An overlay’s gray background showing over the status bar

Problem 3: Sharing With Remote Testers

When sharing prototype links from Framer Cloud with desktop browser users, the prototype renders within its respective device. On mobile, the prototypes render as a native app within the browser UI, making them unviable for user-testing.

Opening the prototype by default on iOS in Safari

The Solution Workflow

The foundation of the workflow I have created come from a post written by Charlie Deets entitled Framer & Sketch: An Intentional Workflow. Building upon Charlie’s workflow, I came up with naming conventions for groups and artboards to easily be organized in and exported from Sketch, compiled an example Sketch file, built an example Framer project, and constructed an easy to follow process for remote users to setup a testing environment on their devices.

Solving Problem 1

Setting Up The Sketch File

When using Framer Flows, I set up my Sketch file to follow the same linear progression that will occur within the prototype. However, any screens that I will be using as headers, footers, keyboards, or overlays globally across the prototype I place before the user journey screens, and arrange them vertically to differentiate them.

Naming Convention for Artboards

After iterating and reviewing with my team, I decided upon a baseline naming system that contains up to five descriptors in camelCase for easy importing. For more information about using camelCase in programming, reference this Wikipedia article.

Sketch Artboard Naming System:

screen / footer / header / keyboard / modal / overlay number
 + 
project name
+
if applicable, current screen’s child overlay / modal / etc
+
device / operating system.

For example:

keyboard1ProjectTablet

screen1ProjectMobile

Device / Operating System

This descriptor can be as equivocal as “Mobile,” or as precise as “GooglePixelXLLandscape.” So far, my most common level of granularity in this respect is “MobileiOS” and “MobileAndroid,” nonetheless, I find it best to be thorough when adopting team or company-wide paradigms.

Child Overlays and Modals

In the case of an overlay, or any other object that is a child of a screen in the user journey, I add a fifth descriptor after the “number” and before the “project name” denoting the object type.

Overlay example:

screen4OverProjectMobile

Modal example:

screen5ModalProjectDesktop

New User Journey

In the case that a user journey forks into multiple unique journeys, I add another two digit number to the end of the first screen number. This added descriptor is helpful in tracking where the original journey forks and the new one begins (I did not include an example of this in my Sketch file, but it is part of the paradigm).

New User Journey Example:

screen601ProjectMobile

Naming Convention for Groups

For Sketch layers to be recognized as layers in Framer, they have to be assigned to a group in Sketch, even if the layer is a single icon, etc. With the vast diversity of group types, I apply a less strict naming system.

Sketch Group Naming System:

object name
+
parent artboard, if applicable
+
device / operating system, if applicable

  1. I omit the “project name” from the group name, as it makes reusing groups across multiple Sketch files less efficient when having to rename company-wide design objects between projects, for example: “hamburger menus” and “back buttons. “
  2. If the group is a single or global occurrence, e.g. a “sign up button” that only occurs on one screen, or a “back button” that occurs across all screens, the groups’ names will be “signUpButton” and “backButton” respectively.
  3. If the group occurs on multiple screens, but interactions with the instances induce different behavior, I add the parent’s main descriptor to the end of the group. In the case of a “yes button” that occurs throughout a sign-up flow but induces different behavior, I would name the group on the third screen “yesButtonScreen3.”
  4. When the group is iOS or Android specific I add the operating system to the end of the name, “passwordInputAndroid.”

I am fastidious about my naming convention with artboards, but do find myself missing groups from time-to-time. I highly suggest naming artboards and groups as you create them, this makes it far easier to keep things organized, and helps you formulate your plain text logic (reference “Step 2” in Charlie’s post for more on that).

Sizing Artboards For Exporting

Framer supports importing from 1x resolution and then converting to the native resolution of the device: 2x, 3x, etc., but I have found importing artboards with native iPhone7 resolution (750 x 1334 px) works best when making prototypes that are responsive across multiple mobile devices. To do this, I simply duplicate my 1x Sketch file, add “Proto” to the end of the new file’s name — denoting it will be for exporting as a prototype, then select all the artboards and use Sketch’s scale tool to scale them up to 200% of the originals artboards. To accommodate the iOS status bar, I subtract 40 px from the height of all the user journey artboards, making them 1296 px tall, and adjust affected layers accordingly.

Grab my example Sketch file here.

Import the Sketch File into Framer

Once I have all of the above set in Sketch, I create a new Framer project and import my Sketch file. Note that I shorten “sketch” to “s” to make the code more succinct. I find it helpful to have the “s” in front of Sketch layers to differentiate them from layers I create in Framer.

Setting up the Framer Project to be Responsive

My methodology for making these prototypes “responsive” does not make them truly responsive from mobile up to a large screen desktop. The code I am using merely scales the Framer projects to fit mobile devices using portrait layouts with resolution ratios of ~1.778, ( iPhone 7: 1334 / 750 px = 1.778, Samsung Note5: 2560 / 1440 px = 1.778, etc). We can reuse this same code to work across other devices with different ratios by changing two values (that will be the third part in this series). If you want a Framer solution to make your prototypes responsive across all devices, I suggest checking out Framer-Adapt (it does require some more work than what I am doing).

To make the prototypes responsive, I use Chris Chen’s code from his post Framer Tips — Responsive for Multiple Devices. For a more in-depth look at what the code is doing, I suggest reading his post, as I am going to just give a quick synopsis for setting up my prototype.

  1. I set the default height and width of the original screens.
  2. I calculate the ratio of the width of the current device by using the built-in Framer object “Screen.width” divided by the default width I set in the previous step: “defaultW,” and assign this value to the variable “ratio.” Note that I made a small change to Chris’s code here to make it slightly more succinct: I use Framer’s built in Screen object to detect the height and width of the current device’s screen, without setting those values as variables, which Chris does in his example.
  3. I make a new layer “all” that I use to wrap all the objects in the prototype, effectively making it responsive. The layer “all” achieves responsive scaling by setting all of its child layers’ width and height to their respective default values, then scales them up or down to fill the current device’s screen size using “ratio.” To ensure the scaling originates from the top left corner of the device’s screen “all’s” “originY” is set to a value of 0, its value of “y” to 0, and then all layers are centered on the x-axis of the device’s screen.

Again, if you want a more in-depth look at why I am doing anything in this step, I implore you to read Chris’s post.

Setting up the Flow Component and Making it Responsive

I love Framer Flows; it has made it far easier for the other designers on my team to create user journeys, but it can have its quirks. To initiate Framer Flows I create a Flow Component and assign some values to it to make it responsive: I set the “parent” of the Flow Component to “all” and its width and height to that of “all.” These values make it scale to fill the entire screen real estate established by the “all” layer.

Next, I set the first screen in the flow, and create any “header” or “footer” layers — in this case the iOS status. For more on what I am doing here check out the Flow Component in the Framer docs.

It’s Magic!

The prototype now scales across all devices with similar resolution ratios. In this picture can see the same prototype rendered on an iPhone5C, Samsung GalaxyS5, iPhone 6s, and iPhone7+.

Setting the Default Layer States

After making everything responsive I create my “default states” for layers that are different upon loading the prototype, than they are in Sketch. In this example, I have created “disabled” states for buttons by using 50% opacity and disabling their event listeners with conditional boolean values. These boolean values change after the user enters text into the buttons’ linked input fields. I also create states for text in input fields that set their width to 0, which hides the text until the user enters their username, password, etc.


Solving Problem 2

Creating Multiple Types of Flow Events

I codify flow events by assigning those that move to a new screen, and child objects that correspond to a flow event within a screen, to their separate respective code blocks. In this example, I have “Flow Events” which trigger moving to a new screen, “Keyboard Flow Events” that show and hide keyboards, and “Overlay Flow Events” that show and hide an overlay that only occurs on one screen.

Flow Events

The first flow event loads the first screen: “flow.showNext(s.screen1ExampleMobile).” This event triggers upon loading the prototype, while user actions trigger all other flow events in this example.

Before the second flow event triggers, when the user taps “s.signUpBtn,” I assign a boolean value stating that the current screen is not “s.screen2ExampleMobile” to establish how the user interacts with the keyboard on the next screen. After the user taps “s.signUpBtn” the prototype transitions to the next screen and makes “screen2 = true.” With this boolean value “true,” interacting with the keyboard on this screen enables different behavior than that which would occur by interacting with the keyboard on a different screen (more on that in the next section).

The next two flow events are triggered when the user taps their respective buttons. These flow events use conditional statements initially set in the “Default States” section to make the buttons “disabled” by ignoring events. When the conditional requirements are met by the user interacting with the keyboard within the respective screens, the buttons become “enabled,” and are actionable for moving to the next screen in the flow.

The last two flow events are triggered by users tapping on a button that then transitions to a new screen.

Keyboard Flow Events

As is evident in the Sketch file, I use a single keyboard across multiple screens; this is made possible by using conditional statements dependent on the screen where the keyboard occurs and user events. In this section, I have three flow events, two that trigger showing the keyboard as an overlay, and one that conditionally hides the keyboard, changes boolean values, and animates layers.

An essential part of the workflow resides here, to make a Flow Component overlay work for a keyboard I hide the gray background that fills the parent screen outside the bounds of the overlay

I do this by assigning the gray background layer “flow.children[0]” to a variable “overlayBack,” and setting that variable’s “backgroundcolor” to “transparent.”

On iOs, and within the desktop browser, this makes the overlay show and hide as it should, but I am running into a bug on Android that sometimes goes to the previous screen when tapping out of the keyboard. Here is a video of the bug on my old Samsung Galaxy S5.

I have only tested this on a Galaxy S5 and a Galaxy Note6, so perhaps it doesn’t happen on more recent devices; nonetheless, this bug impacts my success criteria. I can hack it by making the “overlayBack” variable ignore user events, but this makes the keyboard not hide like it should when a user taps out of it. Thus, I don’t use it as it negatively affects the majority of our users that will be testing this prototype on iOS. Part 2 of this series will be a post on my Android keyboard solution, an example Android Sketch file with bottom navigation, and an example prototype.

Overlay Flow Events

I have two flow events that show and hide an overlay that occurs on the fourth screen of the prototype’s flow. The overlay displays over the fourth screen up to the status bar, by being 1296 px tall. The same essential part of this workflow mentioned in the previous section occurs here; the gray background of the overlay must be set to “transparent” or it will cover the status bar. I use the same code as previously, and it solves the problem here too.

You can play around with and download my Framer project here.


Solving Problem 3

Delivering the Prototype to Users for Testing

UserTesting.com will work with you to test anything: mobile apps, TVs, refrigerators, and everything in between. They allow you to set almost any criteria for user tests, and virtually any instructions or user questions you want. Depending on how you setup the test, or how you ask for one of their amazing moderated tests, you can inject instructions where appropriate on how to use your prototype.

Originally, I came up with a process for users to set up their testing environment that addressed both Android and iOS users, but with UserTesting’s excellent ability to filter users, I found it better to provide iOS and Android specific instructions. I suggest adapting these instructions to meet your needs, but the basic steps are as follows:

On iOS

  1. Have the user download Framer Preview from the App Store
  2. Have them copy the link to your prototype in Framer Cloud on their device
  3. When Framer preview is finished downloading, have them open the app
  4. Next, have them tap “links” at the bottom right of the tab bar
  5. Lastly, have them tap the copied link

If they did everything correctly, the prototype should render full screen on their iOS device.

On Android

  1. Have the user download Framer in the Google Play Store
  2. Have them copy the link to your prototype in Framer Cloud on their device
  3. When Framer is finished downloading, have them open the app
  4. Next, have them paste the copied link and tap the “done” or “next” button

If they did everything correctly, the prototype should render full screen on their Android device.

Wrapping Up

I hope this workflow helps you, and I will post my Android solutions in Part 2. Part 3 of this series will outline how to adapt this framework for other devices and layouts. While I know this isn’t a complete end-to-end solution, I hope it at least provides a foundation that solves a lot of the small but critical problems you might experience.

If you have any questions, improvements, or just want to talk design, feel free to reach out to me on Twitter or comment below.

Thanks to Charlie Deets and Chris Chen for their work that made this workflow possible.

Thank you for reading!