Introducing BonMot 4: Now With Dynamic Type

I wrote BonMot quite by accident. I just wanted to document some typographic tips and tricks that I had learned. NSAttributedString and TextKit are powerful, but they can be impenetrable, and I wanted to shed some light on the situation. However, as I collected my thoughts, I realized that a unified interface for accessing disparate typographic features would be useful, and BonMot was born.

BonMot 4

This time, it was all Brian King’s fault. He was writing a blog post about Dynamic Type, the iOS feature which allows users to customize the text size across all apps at once. As the blog post took shape, and the accompanying sample code grew, we realized that it would fit nicely into BonMot’s future. Four months later, we have:

  • A ground-up Swift rewrite of all of BonMot’s original features.
  • Easy support for Dynamic Type with custom fonts.
  • Support for all of Apple’s platforms: iOS, macOS, tvOS, and watchOS.
  • A few other surprises. For the full list, see the BonMot 4.0 release notes.

If you are already using BonMot 3, you’ll want to check out the Migration Guide. The gist is that BonMot 4’s API is not compatible with BonMot 3, but the conversion should be relatively easy by following a couple of patterns. It also drops the bulk of Objective-C support, but you can still register styles by name in Swift and then get them by name in Objective-C or Storyboards/XIBs.

To see some examples of how BonMot could be used in a real app, check out the example app by cloning the repo or running pod try BonMot and then running the “Example-iOS” target.

Basic Usage

Use a StringStyle to specify the style of your attributed string. Then, use the styled(with:) method on String to get your attributed string:

Glossary

These are the types with which you will most commonly interact when using BonMot to build attributed strings.

  • StringStyle: a collection of attributes which can be used to style a string. These include basics, like font and color, and more advanced settings like paragraph controls and OpenType features. To get a good idea of the full set of features that BonMot supports, look at the interface for this struct.
  • StringStyle.Part: an enum which can be used to concisely construct a StringStyle. You will typically interact with these, rather than constructing StringStyles attribute by attribute.
  • Composable: a protocol defining any type that knows how to append itself to an attributed string. BonMot provides functions, such as the one in this example, to join together multiple Composable values.
  • NamedStyles: use this to register custom, reusable styles in a global namespace.
  • Special: a utility to include special, ambiguous, and non-printing characters in your strings without making your code unreadable.

Style Inheritance

Styles can inherit from each other, which lets you create multiple styles that share common attributes:

XML Parsing

Are you trying to style just part of a string, perhaps even a localized string which is different depending on the locale of the app? No problem! BonMot can turn custom XML tags and simple HTML into attributed strings:

This will produce:

The text, “one fish, two fish, red fish, blue fish,” with the color words rendered in their respective colors

Image Attachments

BonMot uses NSTextAttachment to embed images in strings. You can use BonMot’s NSAttributedString.composed(of:) API to chain images and text together in the same string:

Note the use of the Special type, which gives you easy access to Unicode characters that are commonly used in UIs, such as spaces, dashes, and non-printing characters.

Outputs:

A small image of a face, followed by the text, “label with icon.”

If you need to wrap multiple lines of text after an image, use Tab.headIndent(...) to align the whole paragraph after the image:

Outputs:

A small image of a face, followed by a paragraph of text which has flush left margin alignment.

Dynamic Type

You can easily make any attributed string generated by BonMot respond to the system text size control. Simply add .adapt to any style declaration, and specify whether you want the style to scale like a .control or like .body text.

If you want an attributed string to adapt to the current content size category, when setting it on a UI element, use .adapted(to: traitCollection) as in the above example.

Responding to Content Size Category Changes

If you call UIApplication.enableAdaptiveContentSizeMonitor() at some point in your app setup code, BonMot will update common UI elements as the preferred content size category changes. You can opt your custom controls into automatic updating by conforming them to the AdaptableTextContainer protocol.

If you want more manual control over the adaptation process and are targeting iOS 10+, skip enabling the adaptive content size monitor, and call .adapted(to: traitCollection) inside traitCollectionDidChange(_:). iOS 10 introduced a preferredContentSizeCategory property on UITraitCollection.

Scaling Behaviors

The .control and .body behaviors both scale the same, except that when enabling the “Larger Dynamic Type” accessibility setting, .body grows unbounded. Here is a graph of the default behaviors of the system Dynamic Type styles:

Graph showing BonMot’s scaling behaviors of different text sizes. The important thing to note is that the “Body” type style scales to very large sizes in the “Accessibility” ranges, while the other styles max out at “XXL.”

Most type styles vary by 2 points per step above the “Large” size and 1 point per step below the “Large” size, but they stop growing at “XXL”. Body, on the other hand, grows very quickly in the “Accessibility” range.

 

Towards a More Beautifully Kerned Future

The designers here at Raizlabs are excited to work on projects that use BonMot 4. It allows us to work more closely together to create beautiful typography across all of Apple’s platforms. And now, supporting Dynamic Type is so easy in most cases that including it should be the default choice for projects. I hope you find BonMot as useful as we do. Now go forth, and make beautiful things!


Do you have a project in mind? We’d love to work with you. If you’d like an opportunity to work on projects with us, check out our Careers page. We’re hiring!

One response to “Introducing BonMot 4: Now With Dynamic Type”

  1. I’m using the XML type of styling. I there a way to create an HTML hyper link. for example could I hyper link text by http://www.google.com and the user could click on it and go to the website.

Leave a Comment