Text Styling in iOS

Generate great looking text effects 100% in code

App File Size Matters

When developing iOS apps I try to keep the size as low as I can, since apps over 100 MB cannot be downloaded over 3G and must be downloaded via Wi-Fi, which can be a pain for users. The primary way to reduce the size of an app is to limit the amount of images bundled inside. The usual solution is to store the images on a server up in the “Cloud” and download them after the user has installed the app. While this works, the load time can sometimes be slow, causing a less-than-ideal first experience. Downloading also eats into a data plan if a user is on 3G (why size is limited by Apple to begin with), and takes up space on the user’s device; both are big no-no’s. So as a developer, I try to implement graphics on the fly, in code, as much as possible to avoid these issues.

With iOS we are able to create complex bezier shapes, 2+ colored gradients and add a stroke and/or rounded corner to an image or shape with ease. For text, we can control the color and set a drop shadow with blur, size and offset properties. These are very basic text effects, and advanced text stylings often need to be done in an image.

Styling Text in Code

I recently ran into this Adobe Typekit article, which discusses advanced HTML/CSS text styling techniques. What stood out to me were the CSS snippets, detailing how to reproduce the effects without images. I looked at their examples and realized just how simple it all was. I decided to create a small iOS project incorporating the text styling ideas to see how the technique would work perform on iOS devices.

A screenshot of the finished prototpe project

How it Works

To style the text, a new instance of the text element (UITextView) is created, changing its color and offsetting its position from the original. That is built on by creating multiple duplicates and incrementing the offset to create depth before layering a second set of text elements of a different color to add more complex shading and styling. The draw order of the different colored elements is determined by a boolean value for each style, allowing the elements to alternate. By manipulating the variables, I was able to create a version of each of the styles shown in the original article, I went ahead and added an additional inset style for fun.

The text styles available in the project

Those 4 styles are just a start, there are plenty of potential styles possible with these controls. For example, by simply modifying one offset number, I stumbled upon a really neat shading variation (illustrated in the image below). It’s certainly possible to increase the customizability of the styles and open up the possibilities even more. Adding a third or even fourth additional element type, gradually changing the color of an element as its amount increases or incrementing the scale as the element amount increase, are just a few ways that this technique could be built upon.

Illustration of a shading variation

One benefit of this approach is the ease of changing the text styling. If you use images or a custom bitmap font, you have to go into another program to change the assets and then replace them in the project. This process can be very time consuming if you are continuously making changes. The approach discussed here allows for a simpler solution — just change the color value or offset amount in one line and it’s done.

The code for the project is available on GitHub https://github.com/ManifestTechnology/ios-text-styles.

One Last Thing to Note!

To demo the “live” capabilities of the styling, I used an UITextView so I could edit the text and show it styling automatically. This is not a good idea for a production app! A large amount of re-drawing occurs anytime the text changes. If the style needs more than a couple copies of the text to display correctly (#3 and #4 in the project), it will cause less powerful devices like the iPhone 4 to noticeably delay when typing. Ideally this styling technique should be applied to non-editable text like an UILabel and happen only when a view is first loaded, since the process is somewhat intensive.