Light Mode
Dark Mode
System Colors
For as long as UIKit has existed, it has provided some predefined colors, such as .red, .blue and .yellow
, which you could access statically on UIColor.
Now there’s a new palette of colors prefixed with the word system, including .systemRed and .systemBlue
.
Semantic Colors
In addition to the newly introduced system colors, iOS 13 also provides semantically defined colors. A semantic color conveys its purpose rather than its appearance or color values.
You don’t have to know these colors’ real raw values. Instead, you use them based on their intention and access them as you would other colors: through static calls on UIColor. Examples of semantic colors include .label, .separator, .link, .systemBackground and .systemFill
.
Background Colors
iOS defines two sets of background colors: system and grouped. Each contains primary, secondary and tertiary variants that help you convey a hierarchy of information.
With both sets of background colors, you use the variants to show hierarchy in the following ways:
- Primary for the overall view.
- Secondary for grouping content or elements within the overall view.
- Tertiary for grouping content or elements within secondary elements.
Foreground Colors
For foreground content, such as labels, you can also use various levels of semantic color to convey the importance of the content. Examples of leveled colors include .label, .secondaryLabel, .tertiaryLabel
.
Dynamic Colors
While these newly introduced system and semantic colors are useful, they won’t work in all situations. For example, they won’t help you if you need to use brand colors or your design calls for colors other than those Apple provides.
Before Dark Mode, you could incorporate custom colors in several ways. Developers often use code or Asset Catalogs when using UIColor initializers. Fortunately, Apple updated both to take Dark Mode into account.
UITraitCollection
Before continuing, though, you first need to understand the concept of UITraitCollection.
iOS exposes interface environments for any app through the traitCollection
property of the UITraitEnvironment
protocol. UIWindow, UIViewController and UIView
are all classes that conform to this protocol.
UIColor Dynamic Provider
To construct colors in code, you’ll use a closure based initializer.
@available(iOS 13.0, *) public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)
headerBackgroundView.backgroundColor =
// 1
UIColor { traitCollection in
// 2
switch traitCollection.userInterfaceStyle {
case .dark:
// 3
return UIColor(white: 0.3, alpha: 1.0)
default:
// 4
return UIColor(white: 0.7, alpha: 1.0)
}
}
Asset Catalog
Since iOS 11, you can save your colors in Asset Catalogs and use them both in code and Interface Builder. You can make your colors dynamic with a simple tweak.
Dynamic Images
Open Assets.xcassets
. You’ll see two images named hogwarts and hogwarts-night. Click hogwarts.
In the Attributes inspector, click Appearances
and choose Any, Dark
. A new empty slot appears.
SFSymbols
One of the coolest additions Apple introduced for iOS 13 was SFSympols, a huge set of consistent and highly configurable images. These symbols scale well based on appearance, size and weight. And best of all, you can also use them in your apps for free.
You can download the SF-Symbols mac application in here:
https://devimages-cdn.apple.com/design/resources/download/SF-Symbols-3.2.dmg
houseImageView.image = UIImage(systemName: "house.fill")
houseImageView.tintColor = houseLabel.textColor
SymbolConfiguration:
// Create a configuration object that’s initialized with two palette colors.
var config = UIImage.SymbolConfiguration(paletteColors: [.systemTeal, .systemGray5])
// Apply a configuration that scales to the system font point size of 42.
config = config.applying(UIImage.SymbolConfiguration(font: .systemFont(ofSize: 42.0)))
// Apply the configuration to an image view.
imageView.preferredSymbolConfiguration = config
// Create a symbol image with a tint using UIKit.
imageView.image = image?.withTintColor(.systemRed, renderingMode: .alwaysOriginal)
// Create a new symbol image using the configuration object.
imageView.image = image.applyingSymbolConfiguration(config)
// Create a large scaled symbol image using UIKit.
var config = UIImage.SymbolConfiguration(scale: .large)
imageView.image = image.withSymbolConfiguration(config)
Align Symbol Images with a Text Label by Using a Baseline
NSLayoutConstraint.activate([
imageView!.firstBaselineAnchor.constraint(equalTo: label!.firstBaselineAnchor)
])
// Create a custom symbol image.
let image = UIImage(named: "custom.multiply.circle")
// Add an offset of 2.0 points from the baseline.
let baselineImage = image?.withBaselineOffset(fromBottom: 2.0)
Turn Dark Mode off
- Using the
UIUserInterfaceStyle
key inInfo.plist
. - Set the interface style on the app’s UIWindow, which usually means the whole app.
- Set the interface style for a specific UIView or UIViewController.
For key window:
var window: UIWindow? {
didSet {
window?.overrideUserInterfaceStyle = .light
}
}
For view controller in viewDidLoad()
:
overrideUserInterfaceStyle = .light