Supporting Bold Text with Custom Fonts in SwiftUI
Tags: swift, swiftui, a11y, ios
Published: 2022-07-19 02:10:27

When building for accessibility, there are a lot of preferences to keep in mind! For some people, reading bold text increases their comprehension. Enter the `Bold Text` preference: an iOS setting that increases the weight of all text to ensure this better legibility.

![Users can enable the bold text preference by visiting Settings, Accessibility, Display & Text Size, and toggling the Bold Text switch.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k52c1ri64msgbuzszai5.png)

When a user enables the `Bold Text` preference, everything in the user interface becomes bolder for better legibility. Regular text turns semibold, semibold text turns bold, and bold text turns black (yes, even bold text is bolded!). This also applies to variants like italics.

As UI engineers, we need to account for this preference when we're building interfaces. If you're using the default system font, it's your lucky day — this is already taken care of for you by Apple! But if you're using a [custom typeface](https://developer.apple.com/documentation/swiftui/applying-custom-fonts-to-text), well it's also your lucky day because you found this article!

Here's the code we're aiming for:

```swift
Text("Lorem ipsum dolor sit amet.")
    .accessibilityFont(.body)
```

_**Before you get started,** it's a good idea to alert the designers on your team to the `Bold Text` preference as they will need to purchase the additional weights as needed._

First, let's set up a model that will hold our accessible font data. Here, we'll define both a regular and bold variant of our font that we can switch between.

```swift
struct AccessibleFont {
    var regular: Font
    var bold: Font
    
    init(_ regular: Font, bold: Font) {
        self.regular = regular
        self.bold = bold
    }
    
    func value(_ legibilityWeight: LegibilityWeight?) -> Font {
        switch legibilityWeight {
        case .bold:
            return bold
        default:
            return regular
        }
    }
}
```

Now that we have a model to define our fonts, let's create an example for our body font. When the `Bold Text` preference is enabled, we should use our custom bold font; otherwise, we should use the regular font.

```swift
extension AccessibleFont {
    static var body: AccessibleFont {
        AccessibleFont(
            regular: Font.custom("CustomFont-Regular", 17.0),
            bold: Font.custom("CustomFont-Bold", 17.0)
        )
    }
}
```

Next, we'll define a view modifier (like `.font(_:)`) that we can use on our views. Using the [`legibilityWeight` environment value](https://developer.apple.com/documentation/swiftui/environmentvalues/legibilityweight), we can determine what the true font should be based on the user's preference.

```swift
struct AccessibilityFontViewModifier: ViewModifier {
    @Environment(\.legibilityWeight) private var legibilityWeight
    
    var font: AccessibleFont
    
    func body(content: Content) -> some View {
        content.font(font.value(legibilityWeight))
    }
}
```

For easy reference, we'll also include a handy `.accessibilityFont(_:)` function on `View`.

```swift
extension View {
    func accessibilityFont(_ font: AccessibleFont) -> some View {        
        return self.modifier(AccessibilityFontViewModifier(font: font))
    }
}
```

If we put this all together, we get our original example! Now when the `Bold Text` preference is enabled, SwiftUI will render our text bold in realtime.

```swift
Text("Lorem ipsum dolor sit amet.")
    .accessibilityFont(.body)
```

`Bold Text` is just one preference that users can enable to create an accessible experience. No matter what the user toggles, be it `Bold Text` or `Invert Colors`, we as engineers should work to support it!