Using foregroundColor(), foregroundStyle() or tint() to set text color in SwiftUI
SwiftUI has a few different modifiers that can change the color of text, such as foregroundColor(_:), foregroundStyle(_:), and tint(_:). They provide different functionality, but sometimes overlap and it can be hard to know for sure which modifier to choose. In this post we will go over some common use cases for all three of the modifiers and see which one suits best for what purpose.
Foreground color
foregroundColor(_:) modifier has been available in SwiftUI since iOS 13. It can be used to set a color for all stylable text in the hierarchy including text inside controls like buttons.
VStack {
Text("Welcome!")
Button("Log in") {
// perform login
}
}
.foregroundColor(.teal)
There is also a version of foregroundColor(_:) that returns a Text
rather than some View
when applied directly to a Text
view. This version can be used to set a color for specific words inside a sentence.
Text("The event is on \(Text("Sunday").foregroundColor(.teal)).")
Foreground style
foregroundStyle(_:) modifier was introduced in iOS 15 and instead of simply accepting a Color
type, it accepts a ShapeStyle.
Just like foregroundColor(_:)
, foregroundStyle(_:)
can be used to change the color of all text and other foreground elements in the hierarchy, like images and shapes. But it also provides some more advanced behavior.
Firstly, we can color the text using a gradient, rather than a simple Color
. For example, we can pass a LinearGradient to the foregroundStyle(_:)
modifier, because LinearGradient
conforms to ShapeStyle
.
VStack {
Image(systemName: "globe")
Text("Hello, world!")
}
.foregroundStyle(
LinearGradient(
colors: [.teal, .indigo],
startPoint: .top,
endPoint: .bottom
)
)
In addition, we can provide a HierarchicalShapeStyle, such as primary
, secondary
, tertiary
or quaternary
to modify the current style. The current style is the style that was set higher up in the hierarchy or the default foreground style if you haven't set a custom one.
VStack {
Image(systemName: "globe")
Text("Hello, world!")
.foregroundStyle(.secondary)
}
.foregroundStyle(
LinearGradient(
colors: [.teal, .indigo],
startPoint: .top,
endPoint: .bottom
)
)
In our example the current style is the linear gradient. The image will be displayed with the default primary
hierarchical style, while the text will get the secondary
style, but both will keep the linear gradient.
While foregroundColor(_:)
modifier can also be used to set primary
or secondary
semantic colors, it doesn't support tertiary
or quaternary
styles. Also worth noting that primary
and secondary
colors used with foregroundColor(_:)
don't combine with the current foreground color like hierarchical styles set with foregroundStyle(_:)
do.
Another important difference between foregroundColor(_:)
and foregroundStyle(_:)
is that foregroundStyle(_:)
always returns some View
. It doesn't have a version that returns Text
when applied directly to a Text
view. This means that it can be more efficient to choose foregroundColor(_:)
modifier when setting a color for a single Text
, because it won't create a new view but will rather modify the Text
.
Text("Hello, world!")
.foregroundColor(.teal) // returns `Text`
Text("Hello, world!")
.foregroundStyle(.teal) // returns `some View`
This also means that using foregroundColor(_:)
is the only way to set a different color for words within a string.
// ✅ Sets teal color for "world"
Text("Hello, \(Text("world").foregroundColor(.teal))!")
// ❌ Build error "'appendInterpolation' is unavailable"
Text("Hello, \(Text("world").foregroundStyle(.teal))!")
Tint
tint(_:) modifier was introduced in iOS 15 together with foregroundStyle(_:)
, but its purpose is to override the accent color for the view rather than to set the color of all foreground elements. When we apply a tint on a view hierarchy, it only affects the text inside controls, like buttons and links, not plain Text
views.
VStack {
Text("Welcome!")
Button("Log in") {
// perform login
}
}
.tint(.teal)
tint(_:)
modifier can also be used in iOS to change the color of links embedded inside Text
, as links are considered controls.
Text("Visit our [website](https://example.com).")
.tint(.teal)
Note that in macOS links have a special link color that cannot be changed with the tint(_:)
modifier.
If you have older iOS apps and want to enhance them with modern SwiftUI features, check out my book Integrating SwiftUI into UIKit Apps. It provides detailed guidance on gradually adopting SwiftUI in your UIKit projects. Additionally, if you're eager to enhance your Swift programming skills, my latest book Swift Gems offers over a hundred advanced tips and techniques, including optimizing collections, handling strings, mastering asynchronous programming, and debugging, to take your Swift code to the next level.