Optimized for Touch

In todays world of mobile devices with touch screens we all know that we shouldn’t make interface elements to small or pack them too close to each other because they will be hard to hit. The HIG clearly says that they shouldn’t be any smaller than 44 by 44 points.

44 x 44 points is the comfortable minimum size of a tappable UI element.

Making small things big

In some cases though, what we are drawing on screen is much smaller than that. In such cases we use transparency and cheat! We can make a big, mostly transparent interface element with a small visible element in the center. The full transparent area will be the touch target without the element looking big and bulky. Take for example the native slider and page control. Both of these are visually much smaller than 44 points and still you don’t get frustrated trying to tap on them1.

There are many ways for you to achieve the same thing with your own customized controls. For single icon buttons it’s as easy as giving the button a larger size. The image is going to stay centered making it look like a small button but it will have a large tappable area.

CGRect tappableRect = CGRectMake(50, 100, 44, 44);
UIButton *settings = [[UIButton alloc] initWithFrame:tappableRect];
[settings setImage:[UIImage imageNamed:@"gear"]
          forState:UIControlStateNormal];
visible on sceen tappable area
The larger tappable area of a small button with a single image.

All cases may not be as easy as simply making the control bigger. Perhaps custom drawing depends on the frame it is being drawn into or the control has a visible background that shouldn’t be any bigger. Custom drawing can be done in a smaller rectangle by using CGRectInset(rect, x, y) before the drawing code to create a smaller rectangle to get the measurements from.

For the case with backgrounds and other such elements, we could (but shouldn’t) wrap the control in another view and attach gesture recognizers and actions for control events to it. This would work since we could let still let the original control be the target for those messages. However, it’s much better for encapsulation to make the control itself bigger and have smaller private subviews for backgrounds, etc. that depend on the size of the control. That way nothing outside of the control need to know about these details.

- (id)initWithFrame:(CGRect)aRect {
    self = [super initWithFrame:aRect];
    if (self) {
        CGRect smallerRect = CGRectInset(aRect, 5, 5);
        _background = [[UIImageView alloc] initWithFrame:smallerRect]; 
        _background.image = [UIImage imageNamed:@"background"];
        [self addSubview:_background];
    }
    return self;
}

One step further

Looking back at what the HIG really says about touch targets, the minimum comfortable size is 44 by 44 points. We can make them even bigger if we want to and make them slightly easier to hit. Microsoft has some interesting numbers about touch sizes and successful hit percentages in their documentation for Windows 8 apps. They found that for a 5 by 5 mm touch target about 3% of the touches missed. Similarly for a 7 by 7 mm target about 1% missed and for a 9 by 9 mm target about 0.5% missed. Let’s quickly translate these into points sizes2.

The original iPhone had a 163 dpi display. The retina versions have more pixels but the same number of points per inch. 25.4 mm per inch divided by 163 points per inch gives a point size of 0.1558282 mm. This gives us the sizes in points:

5 mm 32 points
7 mm 45 points
9 mm 58 points

Some may point out that the original iPad actually have a lower amount of points per inch which means that we could make smaller elements and have the same “precision”. However, since the iPad has a physically larger display the finger moves over a larger distances making taps more imprecise. Also, the iPad mini has the same resolution as the original iPhone so unless you want to upset all the mini owners out there it is better to stick with the same point sizes for both iPhone and iPad.

Using the exact same approaches as above we could make elements even bigger as long as there is room on the screen. If you make the size just right, users won’t notice the difference but only be pleasantly surprised that they hit the buttons they are tapping. If however you make these elements way to big then users are going to notice what you are doing and the illusion is broken.

The “optimal” size for a control depends on many things like proximity to other elements, shape and the type of interaction (tap vs gesture) so there isn’t really one magical number I can give you. The only way to find what works best for you is to test many different sizes and see what feels right.

Off-center

In some cases the touch area can’t be in all directions as it might overlap with other touch areas. Instead of just cutting away the overlap we can sometimes move the two views apart, giving them their full size.

In my own experience, we as users make slight adjustments (only a few points) when trying to hit two small elements that are close to each other compared to if the same elements are far from each other. If there is plenty of space we tend to aim for the center but if they are close to each other we tend to over-compensate slightly and aim for the edge that is furthest away from the other element to avoid hitting it.

aims for the center avoids the other button
An illustration of how we as users sometimes overcompensates slightly when two elements are close to each other.

For users who do this we can extend the touch targets more on the side that is furthest away from the other control. We can use CGRectIntersection(frame1, frame2) to get the amount of overlap for the two frames and use that to position them side by side. This will visually move them apart so we need to move their content back together again. If the visual elements of the controls are subviews of the main control view (as described above) then we can shift the view in one direction and the visual elements in the other direction using the transform and sublayerTransform properties of the main views layer.

CGRect overlap = CGRectIntersection(leftView.frame, rightView.frame);
CGFloat xOverlap = CGRectGetWidth(overlap);

CATransform3D moveLeft  = CATransform3DMakeTranslation(-xOverlap/2.0, 0, 0);
CATransform3D moveRight = CATransform3DInvert(moveLeft);

leftView.layer.transform = moveLeft;
leftView.layer.sublayerTransform = moveRight;

rightView.layer.transform = moveRight;
rightView.layer.sublayerTransform = moveLeft;

The image below shows the break down of the nudge back and forth.

move layers apart move sublayers together
An illustration of how the layers are translated apart and their sublayers translated back together.

Just as with growing the tappable areas: if you go to far users are going to notice and it’s going to feel really strange instead. Experimentation is the key to finding what works in your app but you probably shouldn’t go much further than 6 or so points (about 1 mm).


All of this doesn’t apply to all controls in all apps and having to play tricks with visual elements to make them easier to touch can be though of as a “design smell”. That said, I have used this technique in previous projects and generally been happy with the results. Further more, I find that thinking about the tappable areas help make an interface that is less annoying to use.

Do you disagree with me? Great! Tell me all about it on twitter! I’d love to hear your opinions on the topic.

  1. If you didn’t know that you can tap on a page control, now you know. It matters if you tap on the left or right side of it.

  2. All measurements are in mm since there is no predefined screen resolution for Windows tablets.