Tracking & Character Spacing in iOS

In tools like Photoshop and InDesign, tracking is the term that describes the relative amount of spacing between characters in a string of text.

A wonderful bit about tracking: pick a value, and your text will have that same visual style, regardless of the font size. It scales:

See how the spacing in between characters scales with the type size?

Unfortunately, tracking doesn't exist in iOS. What we *do* have available is character spacing:

See how the smaller type sizes are more spread out than their larger counterparts?

See how character spacing doesn't look the same when you change type size? Sketch is a great help with this - when you change a label's text size, the character spacing scales automatically - but this isn't helpful to your iOS dev: if there are 8 different type sizes in your app, then they've got 8 character spacing values to worry about, rather than just a single tracking value.

So: we need a way to represent tracking in code, and when we came up against this problem, I couldn't find a single implementation of this on the web - which meant we had to make one.

I created lots of PSDs and Sketch files, comping up different tracking values and character spacing values, and doing pixel comparisons to figure out what lined up. Once I found a match between tracking, character spacing, and font size, I put it in a spreadsheet and worked out some theories as to how the two were related - and after a bit of algebra, I found that it was actually a *very* simple relationship:

characterSpacing = fontSize * tracking / 1000

At first, I thought, "1000? Really? That's the magic number?" - but then this hypothesis totally worked on other yet-untested scenarios, so that's where we landed.

Here's how you can put it to use:

If you want an easy way to convert between character spacing and tracking, I have a handy Soulver document here

If you're a dev, and you want a category method that'll return a properly-tracked attributed string, you can find one over on GitHub here.

+ (instancetype) dvs_attributedStringWithString:(NSString *)string
 tracking:(CGFloat)tracking
 font:(UIFont *)font
{
CGFloat fontSize = font.pointSize;
CGFloat characterSpacing = tracking * fontSize / 1000;
  NSDictionary *attributes = @{NSFontAttributeName: font, 
  NSKernAttributeName: [NSNumber numberWithFloat:characterSpacing]};

  return [[NSAttributedString alloc] initWithString:string 
 attributes:attributes];
}

Here's how you'd use it in practice:

self.label.attributedText = [NSAttributedString dvs_attributedStringWithString:@"DEVSIGN"
tracking:200
  font:[UIFont systemFontOfSize:17.f]];