My app design workflow
Here it is — my complete iOS, Android and Mac app design workflow, starting from the first time you open Photoshop, to the app release and beyond. Now seemed like a good time to document how I’ve been working, because my workflow is about to drastically change again, with the release of Skala.
I always start with a non-Retina, 1× document size that’s mindful of the smallest or most common target.
For an iPad app, it’s 1024×768. For an Android app, it’s a common device size, in mdpi or dp (density-independent pixels). For a Mac app, it’s often 1280×768 (a frankenstein combination of the 13-inch MacBook Pro resolution horizontally, and the 11-inch MacBook Air resolution vertically, ensuring the app will fit on the smallest current Mac displays). For an iPhone app, it’s 320×568, or one of the sizes below.
There’s many reasons for starting like this. In the same way wireframing helps flesh out concepts, building at 1× helps flesh out view and asset sizes. It means every single thing in your interface will always be snapped to the pixel grid for the 1× size, which is sometimes a technical requirement, but also a good idea — if nothing else, it means you’re working with whole iOS points and macOS points. Working at 1× means there’s no need to remember to keep positions and sizes and layer styles to even integers (0, 2, 4, 6, 8 etc). And it’s so much faster. Photoshop uses far less RAM and is snappier at 1×.
I don’t see my strategy changing any time soon, even though I own a Retina MacBook Pro (most of my design work is still done on a non-Retina Cinema Display). There’s simply way too many advantages, even if you consider the 2× and 3× versions of your assets more important.
1×, 2× and 3× at the same time
However, I’m not suggesting anyone should only work at the non-Retina size — the present and future is high DPI, and there’s a good chance you’ll care about the bigger assets more. I’m advocating working at multiple sizes, and jumping between them as required, which is easily achieved with my Photoshop Actions for document scaling. But, when I make layout changes, I usually work at 1×. Life is so much easier that way.
If your documents are built the right way, you can have precise control over all sizes without any degradation when switching, and you can switch as often as you like. Jump to 2× to work on some button styles, then jump back to 1× to continue with the overall layout. Up again to 3× to edit some layer styles, then back again. One document for everything.
There’s quite a few techniques that allow elements to appear crisp and nicely rendered for all sizes. Here’s some of the methods I use.
Edge effects with gradients
If you can, build edge effects with gradients. Doing so will mean detail is added automatically. Like the shape layers noted above, it’s possible to construct a gradient with sharp and lighter pixel lines at the Retina size and a one pixel line at the non-Retina size. Gradients are amazingly powerful, especially when you keep in mind that they can be applied to a shape layers, strokes, and layer style strokes.
Layer styles and contours
If you’re after better control of layer styles, contours can help. Outer glows can be ideal for effects that look like a single pixel stroke at 1×, but a softer two pixel effect at 2×, and softer again at 3×.
0.5pt and fractional strokes
Or, if you’re after a 0.5pt stroke that appears as a single pixel stroke at 2× and a softer single pixel stroke at 1×, vector strokes can be non-integer values (layer style strokes can’t).
The same can be done to target a single pixel stroke on a @3x display — a 0.33pt stroke will scale up to 1px.
Enabling Photoshop’s pixel snapping lets you create sharp objects. If you’d like to move something to precisely half a pixel, disable pixel snapping, zoom to 200% and press an arrow key to nudge exactly half a pixel. This lets you make Retina resolution changes when working at a non-Retina size. Other zoom levels can be used to nudge other fractions. This means you can construct objects that will render as a single pixel 100% opacity line for the 2× size, but a single pixel 50% opacity line at the 1× size.
Mask feathering is a great way to soften shape layers. Pretty much anything that can be built using a layer style can be built using a separate shape layer with mask feathering, but sometimes with more precision, because shape layers can be offset by non-integer amounts and contain non-integer mask feathering.
There is one giant caveat though — mask feathering doesn’t scale with the document, which is why David Jensen created a few mask feather scaling scripts, which are on GitHub as part of the free Bjango Actions download. If you’re using my Scale Document actions to jump between 1× and 2×, mask feathering is scaled automatically (you will need David’s scripts installed though).
Bitmap layers and bitmap masks are evil, if you’re creating a document that can be freely scaled up and down. Most masking — even soft edges — can be accomplished using shape layers, groups and mask feathering. Masking using vectors in Photoshop is insanely powerful. Pretty much anything you can imagine is possible, even if it’s a little cumbersome to build.
There’s typically two types of textures I work with. I want large textures and photos to scale with the document. The best way to build something like that is to work at the 2× size, then turn the layer(s) into a smart object. Doing so means it’ll appear pixel perfect at the 2× size and be bitmap scaled down to the 1× size.
Things that are small and subtle, like noise, I usually want to remain at 100% scale for both sizes. Using a smart object doesn’t produce the correct behaviour, because smart objects scale with the document. For those kinds of things, I use pattern layers or pattern layer styles.
There is one issue though — like smart objects, patterns scale with the document. If you add a pattern at 100% while working at 2×, the pattern bitmap scales to 50% at 1×. This will turn a high quality noise texture into a blurry mess. Enter David Jensen again, with another script: Scale Patterns to 100%. This script is also included in the Bjango Actions download, and is automatically applied when using my scaling actions.
Implementing things you want to scale as smart objects and things you don’t want to scale as patterns means document scaling can be automated. And if you’re going to switch between 1× and 2× regularly, automating the entire process is critical.
Realtime device preview
If I’m working on an iOS or Android app, I’ll check the design throughout the entire process using our app, Skala Preview. It’s been built with working at 1× or 2× in mind — simply double tap in the preview area to change between 100% and 200% scale, letting you fill the screen if you’re working at either size. If your mock ups include iPhone or iPad chrome (an image of the actual device as a border), tap and hold with two fingers to centre, letting you position the preview without chrome on the device itself. Please note that this assumes you’ve set up your Photoshop document so that the iPhone and iPad chrome are even on top and bottom, and left and right.
I apologise for the shameless plug of Skala Preview. I really would be lost without it though. Plus, it’s free, so you may as well try it out.
Exporting using slice sheets
Here’s the part where you may think I’m crazy. All the projects I’ve worked on in the last few years have ended up with two sets of Photoshop documents — one for mockups and another set up as slice sheets for exporting final assets.
There’s several advantages to working this way.
In mockup documents, pretty much anything goes, within reason. I make sure everything is well named, app states are grouped, and I try to build things how I’ll need them later, but the occasional bitmap layer is fine. Sometimes bitmap layers are far faster to work with, letting you try out different layouts quicker.
I often have only one Photoshop document per size and orientation. A portrait only iPhone app would be contained within one PSD that has app states separated using groups. I don’t use or like layer comps, because I find them incredibly fragile (Photoshop CC 2014 did solve many of my complaints about layer comps though). Using groups means duplicating many items, but I find that more workable than all the alternatives. If there’s stuff you really want to keep in sync across many groups, layer tags might be a good method. It’s a fun idea, but I don’t use them very often.
My export documents are flat sheets, with each asset set up as a separate slice. This lets me clearly see and edit export boundaries, as well as set filenames using slice names. Being laid out flat means working in an environment where transparency is obvious and vector points can be marquee selected without fear of selecting something on another layer.
QuickLook in the Finder can be used to visually locate an asset without opening a PSD, even on computers where Photoshop isn’t installed. This is so handy when coming back to an old project. Repeated for impact: Using only the Finder, you can locate any asset in a big project within seconds, then open it in Photoshop to reveal the filename, edit and re-export.
Because slice sheet documents only contain a single copy of elements you need in the actual app, they’re small and fast to work with. Really, really fast.
Slice sheets sound cumbersome to set up, but they’re actually really quick, once you get the hang of it. As you may expect, I have some actions to help with the process (they’re included in my Bjango Actions).
Running the Show Optimal Size action creates a bitmap layer showing the smallest possible asset size for the current marquee bitmap selection. This is a great way to trim excess padding.
Running Make Slice From Layer makes a slice from the currently selected layer. In my case, that’s often the layer Show Optimal Size just created.
I don’t always want the smallest possible file dimensions though — I find it important to control this process manually, because I often want to allow a few spare pixels to let me alter the design at a later date, or to denote a larger tap size (a little bit of blank space typically doesn’t make a notable difference to file size or memory used).
Make Slice From Selection, also included in the Bjango Actions, is another quick way to create a slice. I’m not sure why, but I find the marquee selection tool easier to use than the slice tool itself.
Slices can also be kept in the document, but set to not export, if an asset is not longer needed, but you don’t want to delete it yet.
With your slice sheet is set up, using Save For Web will export all slices as images. Exporting a single set of images isn’t enough though — we need the 1×, 2× and 3× sizes, and we need the 2× and 3× filenames to have a @2x or @3x suffix. Enter Hazel.
Moving and renaming using Hazel
Hazel is a tool for automatic file organisation. It can rename files placed in a specific folder, then move them somewhere else. Perfect.
With a slice sheet document set up, I run an action that performs the following:
- Save For Web all slices to a known location, a folder called “Export”.
- Scale the document by 200%.
- Scale all mask feathering by 200%, using a script.
- Scale all patterns to 100%, using a script.
- Save For Web all slices to a known location, a folder called “Auto @2x”.
This results in the 1× assets being placed in the Export folder and the 2× assets being placed in the Auto @2x folder. Hazel watches the Auto @2x folder for new files, adds @2x to their filename, then moves them to the Export folder. I have a similar setup for @3x renaming and moving as well.
Here’s a video of the entire process in action. It’s running a bit slower due to the screen recorder. However, even at full speed, the two scripts (Scale Patterns to 100% and Scale Mask Feathering by 200%) do take a while to step through every layer.
Android, Windows and asset subfolders
Matt has a very similar workflow to mine, which is no surprise given how often we chat about these things. He was working on an Android app and needed to adapt the workflow — Android uses subfolders (drawable-hdpi, drawable-xhdpi etc) for the different asset sizes, rather than file suffixes. Save For Web exports all images to a single folder, so we needed to find a way to automate the process for Android’s subfolders.
The solution we came up with was to add hashes to the slice names — by naming slices with a character to separate the folder and file name, it is possible to get Hazel to organise everything after the export.
The same solution would work for Windows 8, which also uses subfolders to separate assets for different pixel densities.
The Hazel rule is available as part of the Bjango Actions.
Automated exporting should save you time overall, even if a fair bit of setup is required initially. However, its real strength comes from being repeatable and predictable. Since working this way, it has been common for us to re-export complete sets of image assets 30 or more times while building an app. We treat image exporting in the same way a programmer treats clicking Build in Xcode — make some changes, build the assets, see them in action.
I simply can’t understate how much this has helped us, especially when used in combination with GitHub. It has made our design process very similar to most developer’s coding process. It also means we can rough-in image assets if we’re fairly certain of the size, they can be added to the app, then I can refine and re-export over time, meaning code and design can progress in parallel.
This does put some additional pressure on the design side — all image names must be exactly how they appear in the app, so we have a fairly strict naming convention we stick to, and if images need to be renamed, that has to be done in the slice sheet. Resist the urge to rename files in the Finder, because you’ll pay for it later.
Out of sync
Astute readers will note the likelihood of my mockup and export documents being out of sync. That’s fine. Once the mockups are finished and the real app is being built, they’re not going to represent the latest changes anyway. The mockups are just a stepping stone to the final product. It’s the export documents that need to be pristine, up-to-date and well organised, because they are where future changes will be made.
As usual, this advice is provided to help beginners and to spark discussion with experts. If you think I’m doing it wrong, feel free to let me know.
Published 1 June 2013.
Updated 22 September 2014 to include lots of 3× info and refresh screenshots.
Updated 1 February 2016 with the latest iOS devices sizes and other improvements.