A Practical Introduction to Photoshop for iOS Developers
What follows is a crash course in Photoshop for iOS developers. I’m going to take a very nuts-and-bolts approach. I hope to demystify what it is that an iOS app designer means she says things like “working in vector” or “pushing pixels.” Beware the following caveat: this is an article about tools, not design. If this were an article about ice sculpture, it would teach you how to turn on the chainsaw. It’s up to you to sculpt an angel without losing a limb.

I’ll give you a winter prediction: it’s gonna be cold, it’s gonna be grey, and it’s gonna last you for the rest of your life.
Photoshop is a big beast. In some places its interface design capabilities feel tacked-on as an afterthought. When mocking up an iOS app in Photoshop, you’ll find that you only need a fraction of the available features. The unused features make it hard for newcomers to know where to begin. It helps to find your bearings before opening your first document.
A Stack of Layers
A photoshop document is a stack of layers that are composited in real time down to a single two-dimensional image. Every layer has several components:
1. Layer Content
Setting aside any other effects or styles that may be applied, a layer’s content is its most basic component. There are four main layer types, each with it’s own kind of content: raster, fill, shape, and smart object.
Raster – Raster layers are a (virtually) infinite canvas of bitmapped pixels. Photographers typically work with raster layers.
Fill – Fill layers fill the document canvas with either a color, a gradient, or a pattern. When designing an iOS app, you’ll almost exclusively be working with both shape layers and fill layers (more on this below).
Shape – Shape layers are vector paths filled with a solid color. Technically, a shape layer is just a fill layer with a vector mask. But it’s helpful to think of them as a separate type, since you’ll use them much differently.
Smart Object – Smart Objects are akin to blocks in Objective-C. Much like a block is both executable code and an object, a Smart Object is both a layer and link to another Photoshop document. Smart Objects are useful when mocking up new screens, but you’ll want to avoid them when creating image resources for production use.
2. Layer Masks
Every layer has an optional set of masks, which function like stencils. An individual layer can have up to two masks: a raster mask and vector mask (except shape layers, which can only have a raster mask, since they already have a vector mask by definition). For example, a raster layer could have a heart-shaped vector mask:
3. Layer Styles
Each layer has an array of options that apply styles to the inner and outer regions of its content. Layer styles include things like drawing a border around the visible edges of layer content (a stroke), or adding a drop shadow that casts a shadow on layers underneath.
There are lots of layer styles, each with its own suitable purposes and range of possible effects. I’ll go into detail about some of them later on.
4. Blend Modes and Opacities
Non-opaque areas of layer content are composited with underlying layers according to the selected blend mode for that layer. The blend mode selector defaults to “Normal”, but there are many other choices. Many of the blend modes have exaggerated photographic effects, as you can see here:

Three blend modes, same shape and color.
Except for certain specific cases, you should always set each layer’s blend mode to “Normal.” When it comes time to save image slices as PNGs to use in your app, Photoshop will blend non-opaque areas with an empty translucent background, thus losing the information produced by a dynamic blend mode.
There are also two opacity sliders for each layer. The one officially dubbed opacity adjusts the opacity for the entire layer, including any layer styles that have been applied. The other opacity slider is called fill. The fill slider adjusts the opacity of the layer’s contents without affecting the opacity of the styles. The difference between opacity and fill is easier to understand with a visual example:
5. Layer Groups
Layers can be organized into a group, which looks like a folder in the the layer panel. Since Photoshop CS6, layer groups have their own layer styles and masks, as well as opacities and blend modes. This can be difficult to wrap your head around in the beginning, but it comes in handy when mocking up complex layouts.
Working in Vector
With new device form factors always on the horizon, it’s important for iOS designers to build mockups and image resources in ways that are easy to scale up or down as needed. The recommended approach is called “working in vector,” which is not necessarily a reference to working with SVGs. Most iOS app image resources are loaded as PNG files. But that doesn’t mean the Photoshop documents that generated them aren’t vector-based.
A vector-based Photoshop document is composed entirely of shape layers and fill layers. It is trivial to scale a non-retina @1x resolution document up to an @2x document, as long as it’s entirely composed of these two layer types. It’s often as simple as using the “Image Size…” menu item.
Some designers do all their mockups at non-retina scale and then scale up to retina for final processing. I prefer the opposite. Others make large sprite sheet documents that have both normal and retina scale images for app resources, side-by-side, sliced up for easy exporting. Whatever your approach, the most important thing is to avoid using raster layers at all costs. Scaling up a raster layer to a higher resolution will make your hard work look terrible:
Sample Project: A Classic Button
Let’s put together everything discussed above in a sample project. It may not be in-fashion these days, but a classic iOS button is a great learning project for experimenting with shape layers, layer styles, and vector-based documents.

“Gee, our old LaSalle ran great…”
1. Create a New Document
A document for mocking up an iOS app should be in the RGB color space with a resolution of 72 pixels per inch. I usually work in a 16 bit color depth since it produces smoother gradients. If you plan on exporting PNGs for use in an actual app (say, for button states), be sure to have a transparent background.
2. Disable Color Management
Notice in the screenshot above that I selected “Don’t Color Manage This Document.” Photoshop processes color differently than other OS X apps. When you’re designing for mobile apps or for the web, you’ll want to disable all forms of Photoshop’s color management. In addition to disabling color management for all new documents, you’ll also want to select “Monitor RGB – Display” for “RGB Working Space” under the “Color Settings…” menu item:
Using the native RGB space of your Mac’s display, your Photoshop document will look similar to what you’ll see on a device. But there’s no substitute for using something like Skala Preview to preview your designs in situ on an iPhone or iPad. Marc Edwards from Bjango has an excellent article that goes into detail on color management and Photoshop.
3. Enable Pixel-Snapping
All vertical and horizontal edges in your mockup should be aligned to whole integer pixel margins. It’s possible for shape layers to have path segments that are out of alignment with whole pixel margins. When this happens it makes the edges of your shapes look fuzzy:
There is an option in Photoshop’s general preferences screen called “Snap Vector Tools and Transforms to Pixel Grid” which, when enabled, makes this much easier to manage.

This button toggles pixel snapping.
If you’re working on a retina resolution document (1536 by 2048 pixels for a portrait iPad), try to make all horizontal and vertical edges line up with even-numbered pixel margins. That way when you scale the document down for a non-retina screen, your edges won’t fall on sub pixel boundaries (which leads to fuzzy edges).
4. Add a Solid Color Fill Layer
Using a fill layer makes it easy to non-destructively tweak the background color of the document whenever you wish. To speed up my work, I use John Gruber’s system keyboard shortcut for the Help menu search box. I just start typing N-E-W F-I-L-L until the desired item appears in the drop-down.
After picking a color, your document will have a backdrop to go behind the button.
5. Add the Button Shape Layer
First put up some guides (either with the menu item or manually by dragging inward from the rulers) to get the size and position of the button the way you want.
Next, choose the rounded rectangle shape tool from the tools panel. You may need to click and hold to switch between the shape tools from the sub-menu.
When you’ve selected the rounded rectangle tool, the options toolbar changes to show the options for this tool, including a corner radius:
If you can’t see the options menu, toggle it’s visibility under the “Window” menu item.
Change the corner radius to something neither too small or too large. Since this is a big button at retina scale, I think 16 pixels looks good. Now draw in your shape:
Notice that there is now a layer in the layers pane called “Rounded Rectangle 1”. I recommend giving a proper name to every layer in your document.
6. Change the Button’s Color
To change the fill color of your rounded rectangle, double click in the thumbnail preview for that layer in the layer pane (can it be less obvious?). This will make the color picker appear. Pick a bright blue color, but not too saturated. Something like this:
7. Experiment With Layer Styles
With the options in the Layer Styles window, there is shocking variety of possible effects you can achieve – even with just a single shape layer. The full breadth of each tool is outside the scope of this post, but I’ll give you a taste with the following recipe. To show the Layer Styles window, double click in the empty gray area of a layer row in the Layers Pane (yeah, I know, even less obvious).
Inner Shadow
Inner Glow
Gradient Overlay
Gradient Overlay Submenu
Outer Glow
Drop Shadow
Bonus Points: Add an Icon Shape Layer
For bonus points, switch the shape tool to the custom shape option and add a white icon to your button:
Style the icon to make it look sort of like mine does here. Remember this star is just one shape layer. You should be able to create this glossy, raised look with just its Layer Styles window alone.
Basement Menus and Breaking the “Rules” of App Design
Luis Abreu has an interesting breakdown of basement menus in his recent post: Why and How to avoid Hamburger Menus. It has some great points and is certainly worth a read, but it got me thinking about when to break the “rules” of UI design.
During the course of my design critique of Glassboard for iPhone, I listed the questions I ask myself when considering whether to use a basement menu in an app:
Is there a single screen where the user spends most of her time?
Is there a dynamic number of equally-weighted menu items?
Are the contents of the menu easy to memorize?
Are hard-to-memorize items used infrequently?
Are the number of items kept to a minimum?
It’s important to note that this is a list of questions, not a list of reasons. There are times when a basement menu is a bad choice, and there times when it is a great choice. Every app has a unique set of goals and constraints. It’s up to the designer to find a good solution. Don’t limit your choices prematurely by assuming some options are off-limits.
As I’m discovering with Unread for iPad, even design patterns that are almost universally maligned can sometimes be the best choice. Apple, via moments like an on-stage presentation by Phil Schiller1, taught us all how much better iPad apps are than most Android tablet apps. The latter are typically just scaled-up versions of their phone-form cousins, whereas iPad apps are designed to take advantage of the iPad’s display. I don’t know about you, but I found myself immediately agreeing with Schiller’s comment that day. From then on, I took it as a given that no self-respecting app designer would design an iPad app that is just a blown-up form of its iPhone version.
But a scaled-up iPhone layout turned out to be the best choice for Unread on the iPad. As I describe in detail here, a full-screen iPad layout is more faithful to Unread’s goal of a relaxed, focused reading experience. It also makes it possible to navigate almost anywhere in the app without having to reposition your hands from the edges of the device.
The fun and the frustration of creative work are two sides of the same coin. Treat every project like it’s your first. Marc Edwards shared a fantastic anecdote about this recently. He recalls what it was like to work with a lead designer who, from the outside, appeared to be an indecisive flake:
Then it clicked.
He’d intentionally try different and crazy things, knowing that most wouldn’t work. He didn’t care. He didn’t care and it didn’t matter — we’d end up in places we never would have if we over thought the layout. The question wasn’t “what is the best way?”, but “what are the many ways?”, deferring judgement until the last possible moment. Judgement may feel good, but it has no value. The value is in the outcome.
And the outcome was often solid, stunning designs that were unconventional. Non-obvious solutions. From the outside and to other art directors, it appeared magical. But, from within the process, far less nuanced and intentional.
No Friday App Design Review This Week
I meant to post this yesterday, but there will be no Friday App Design Review this week. Family is visiting us. I’m working on a special post for iOS devs next week, though.
AutoLayout Myths, Table View Performance, and Side-by-Side iPad App Multi-tasking
With the prospect of a new iPhone form factor and/or side-by-side iPad app multi-tasking on the horizon, iOS app designers and developers are likely to face new challenges when building their apps. Since it was introduced, a lot of people have championed AutoLayout as the cure for these challenges. This post is going to debunk that myth. Or more fairly, this post will show the limits of what problems AutoLayout is able to solve.
Multiple Layouts
For the purposes of this post, let’s assume you’re an iOS app developer planning the architecture for an app like Unread. We have to plan for scrollable table views with as many as 20,000 rows. Each row has a dynamic height based on several factors:
- The length of the title, blog name, and article summary.
- The presence or absence of an image thumbnail.
- The user’s chosen font size.
So, given a container with width w, how should we layout our elements?
As the developer, we’ve been handed some design mockups which we’ll use to write code that calculates the size and position of all our elements. Given a container with width w1, our layout might look like this:
The math and logic required to calculate the position of all these interface elements can potentially become very complex. It is this problem that AutoLayout is designed to solve. AutoLayout makes it easier to write and debug code that calculates the layout of a set of interface elements for a given container size.
It’s important to note that you can’t assume that the container width will always be equal to w1. Apps might have to handle at least two possible container widths: portrait and landscape. So what does our layout look like for a second width w2?
This layout is much different from the first one. AutoLayout makes it easier to calculate the correct positions of all these elements. But as the app developer, your problems are much bigger than just calculating a layout for a given container. You also have to deal with extrapolating that calculation across thousands of model objects and many possible containers. This problem is much more difficult and is beyond the scope of AutoLayout.
Cell Heights and Performance
Notice that the second layout above produces a different total height than the first. What are the implications now that your app has two layouts with two different heights?
When a table view is loading, it needs to know how many rows it will display and how tall each individual row will be. For designs that produce dynamic row heights (as the design above does), these metrics can be very expensive to calculate. You don’t want your app to pause for several seconds while calculating these heights. So what are your options?
Use the new estimated row height API. – On first blush this seems like the best answer. The problem is that
estimatedHeightForRowAtIndexPathhas many bugs. I’ve gone into greater detail on them in another blog post, but the short version is that any app feature that requires accuracy (such as tapping the status bar to scroll to the top of a list) simply won’t work with a table view that implements that method. So this is not a good solution.Pre-calculate and cache all row heights. – Using iOS’ ability to perform work in the background, your app can calculate the height of every table view row ahead of time. Then your table view will load “immediately,” without pausing the execution of the main queue.
Pre-calculation is a better solution, if you can pull it off. It’s difficult to do correctly. There are many factors to consider:
- How many layouts must you pre-calculate for? Portrait and Landscape? Are there others? Every new layout multiplies the total amount of pre-calculation that must be performed.
- What if the user changes themes or font sizes while a long-running pre-calculation is underway on a background queue?
- If you’re caching the results of the background calculation, what kinds of events would invalidate that cache? Date changes? Content changes?
- What if a table view will have 20,000 items in a single list? Is it possible to perform all that work on an older device like an iPad 2, even on a background queue? It could take 15 to 30 seconds to do all that work on an older device. Will you then have to re-write your model collections to support paging in new content as needed?
iPad Multi-tasking & Performance
In the example above, your app was already strained to achieve good performance with only two layouts of static widths. If iOS 8 allows iPad apps to enter a multi-tasking mode with dynamic widths, this would exponentially increase the difficulty of achieving good table view performance. Pre-calculation would be practically impossible.
Assuming the estimated row height API is still buggy and pre-calculation is impossible, the only other alternative would be for devs to start over from the beginning with a design plan that doesn’t allow elements with dynamic heights to also have dynamic widths. This would make good performance achievable, but it would defeat the purpose of a flexible app container. It is for this reason that I think if Apple adds iPad app multitasking, it will only be by scaling app containers without changing the underlying logical widths (768 or 1024 points for portrait or landscape respectively).
The Point
The point to remember is this: AutoLayout makes it easier to calculate a single layout for a single container, but it is irrelevant to the challenge of efficiently calculating a large number of layouts for multiple possible containers.
Friday App Design Review – AnyList, Shared Grocery Lists
Every Friday I will post a detailed design review of an iOS app. If you’d like your app to be considered click here for more information. I am also available to consult privately on your projects.
This week’s Friday App Design Review is AnyList for iPhone, from the service of the same name. AnyList makes it easy to create grocery and shopping lists shared between you and and other members of your household.
My wife and I have been using AnyList for the last week and it works as advertised with fast, reliable syncing. We really like how it automatically sorts new grocery items by category. For the most part, we’ve been very pleased. It’s probably going to be our go-to app for grocery shopping from now on. I do have some qualms about the design, however, which I’ll address in this post.
AnyList is a freemium app, so rather than spend half of this post documenting how the app works, you should just download it now and try it for yourself. There are lots of extras and features peppered throughout the app, like built-in recipe storage, but this review is going to focus on just the list screen. My comments are applicable to the app as a whole, so hopefully this narrow focus will help clarify my points.
TL/DR
- Avoid fuzzy implied borders.
- Push beyond a stock aesthetic.
I. Avoid Fuzzy Implied Borders
There are two kinds of borders in an iOS app: real and implied. A real border should be self-explanatory. An implied border is obvious in context, even though it isn’t represented by a concrete visual border.

Most iOS toolbar icons have implied borders.
Implied borders are accomplished through the visual rhythm of multiple elements, identical in size and proportion, spaced at regular intervals. Elements of different sizes or shapes, or with an irregular arrangement, result in fuzzy implied borders. In an iOS app, fuzzy borders should be avoided, especially when arranging tappable elements.

The current AnyList list screen.
AnyList’s list screens suffer from numerous fuzzy borders. Because section headers don’t span the width of the screen, and because sections with only row don’t have any row separators, it is often difficult to tell where one tappable area ends and another begins.

Dark areas are the most visually confusing.
To sharpen these implied borders, the section headers would need to span the width of the screen:
By extending the section headers, the tappable areas of both the rows and the detail buttons becomes more obvious. Your eye would perceive the implied borders more easily:
While this is easier to use, it isn’t visually interesting. Perhaps there is a way to sharpen the fuzzy implied borders while also adding tasteful visual interest.
II. Push Beyond the Stock Aesthetic
AnyList adheres almost exclusively to the stock visual language of iOS 7. Buttons and icons are thin and wispy. A predominantly solid white background color is interrupted only by occasional horizontal borders. Unadorned text abounds, except where a single accent color is in use. With few exceptions, every interface element looks the way it would if you had just dragged it from the new object panel in Interface Builder.
This stock look doesn’t do AnyList any favors. As a subscription service, AnyList aspires to build a long-term relationship with its customers. Just like a dating relationship, this story will begin with visual attraction. AnyList needs a strong personality to draw in new customers and to help create an emotional bond with them as they grow familiar with the service. The current stock aesthetic feels too utilitarian.
The outliers in the current aesthetic are the AnyList logo and word mark:
The rounded, perky logo is fantastic. I love the movement it suggests. It looks almost anthropomorphic, like the Pixar lamp bouncing on a ball. What would AnyList for iPhone look like if the character of the logo were applied throughout the app? I’ve made a mockup of one possible approach:

My rough sketch of an alternate design.
Here’s the rationale for my suggested changes:
Get rid of Helvetica.
I’ve changed Helvetica to Creighton Pro. Helvetica is not only stock, it’s a poor choice for body text. AnyList is a predominantly text-based app. The font choice has the greatest influence on the look and feel of the app. Creighton Pro is just one of many possible alternatives. It echoes the rounded corners of the AnyList logo and word mark. It’s readable, stout, and casual.
Make the toolbar icons meaty.
While I’d argue that iOS 7’s wispy icons are terrible in general, in AnyList’s case they’re also not brand-appropriate. In this mockup I’ve made the toolbar iconography meatier and more rounded, like the logo.
Improve the section headers and row separators.
The pointed arrow section headers don’t fit within the aesthetic suggested by the AnyList logo. I replaced them with the full-width roundrects, which echo the similar shapes found in the AnyList logo. The repetition of these shapes makes the logo feel inevitable in hindsight. It creates a strong visual association between the layout of the app and the AnyList brand. This look also has the extra benefit of solving the fuzzy implied border problem described above. I’ve added negative space to the right margin. Horizontal row separators no longer touch the either edge of the screen. This subtle choice is suggested by the AnyList logo itself. It also helps visually separate the scrollable content from the navigation bar and toolbar.

























