If you are immersed in the world of Swift programming, you know that creating clean, accessible, and maintainable user interfaces is one of the most critical and important tasks in our day-to-day. As an iOS Developer, we often find ourselves designing visual components that combine text and iconography. This is exactly where the Label component shines, and more specifically, the labelStyle modifier in SwiftUI.
In this extensive tutorial, we are going to dive deep into what it is, how it works, and how you can make the most of labelStyle to create consistent cross-platform applications across iOS, macOS, and watchOS using Xcode.
Whether you are taking your first steps in SwiftUI or you are a Swift veteran looking to perfect your view architecture, this article will provide you with all the tools you need.
1. What is a Label in SwiftUI?
Before diving into styles, it is essential to understand the base component. In modern Swift programming with the arrival of SwiftUI, Apple introduced Label, a standard view specifically designed to represent a user interface element consisting of a title (usually text) and an icon (usually a system image or SF Symbol).
Historically, if an iOS Developer wanted to show an icon next to text, they would have to create an HStack containing an Image and a Text.
// The old (and less semantic) approach
HStack {
Image(systemName: "star.fill")
Text("Favorites")
}
Although this code works in Xcode, it lacks semantic context. The accessibility system (VoiceOver) reads it as two separate elements if they are not explicitly grouped, and the operating system doesn’t know how to adapt this HStack in different contexts (like toolbars or menus).
To solve this, SwiftUI gives us the Label:
// The modern approach in SwiftUI
Label("Favorites", systemImage: "star.fill")
This simple component is semantically rich, accessible by default, and most importantly for this article, highly customizable through its style.
2. What is labelStyle in SwiftUI?
The labelStyle modifier in SwiftUI is a powerful tool that allows an iOS Developer to dictate how a Label and all child labels within a view hierarchy should be rendered.
Instead of applying colors, fonts, and spacing individually to each Image and Text, labelStyle allows you to define a design “theme” or “behavior.” This follows the SwiftUI design principle of separating content from its presentation.
The basic syntax to apply a style is as follows:
Label("Settings", systemImage: "gear")
.labelStyle(.titleOnly)
Just like with buttons (buttonStyle) or lists (listStyle), applying a labelStyle in SwiftUI on a parent container will affect every Label inside it, which is a fantastic trick in Swift programming to keep your code DRY (Don’t Repeat Yourself).
3. Built-in Label Styles (Native LabelStyles)
The Swift ecosystem provides us with several native styles ready to use directly in Xcode. Let’s review them and see how they behave.
A. DefaultLabelStyle (.automatic)
This is the default style. SwiftUI automatically decides how to display the Label depending on its context. For example, in a standard list on iOS, it will show both the icon and the title. In a toolbar (Toolbar), it might only show the icon depending on the available space.
Label("Profile", systemImage: "person.crop.circle")
.labelStyle(.automatic)
B. TitleOnlyLabelStyle (.titleOnly)
As a good iOS Developer can guess from the name, this style completely hides the icon and displays only the text. It is extremely useful when you are reusing a view component in an area where space is limited or the iconography is redundant.
Label("Notifications", systemImage: "bell.fill")
.labelStyle(.titleOnly)
// Screen result: "Notifications" (no bell)
C. IconOnlyLabelStyle (.iconOnly)
The counterpart to the previous style. It shows only the icon and hides the text. This is a de facto standard in Swift programming for NavigationBar or TabBar buttons.
Label("Search", systemImage: "magnifyingglass")
.labelStyle(.iconOnly)
// Result: 🔍 (without the word "Search")
Accessibility Note: Although the text visually disappears, SwiftUI is smart. VoiceOver will still read the word “Search”, ensuring your application remains 100% accessible to visually impaired users.
D. TitleAndIconLabelStyle (.titleAndIcon)
This style forces SwiftUI to explicitly show both the icon and the title side-by-side, regardless of the context.
Label("Download", systemImage: "arrow.down.circle")
.labelStyle(.titleAndIcon)
4. Creating a Custom LabelStyle in Xcode
The true power of Swift programming is unleashed when default styles aren’t enough for your app’s design. As an iOS Developer, you often receive Figma designs that don’t fit Apple’s generic standards. This is where we need to create our own labelStyle in SwiftUI.
To create a custom style, you must create a struct that conforms to the LabelStyle protocol. This protocol requires you to implement a single method: makeBody(configuration: Configuration).
Example 1: The Vertical Style (VerticalLabelStyle)
Suppose we want the icon to appear above the text, centered, instead of to the left.
import SwiftUI
// 1. We define our custom style
struct VerticalLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
VStack(alignment: .center, spacing: 8) {
// configuration.icon represents the Label's image
configuration.icon
.font(.system(size: 32))
.foregroundColor(.blue)
// configuration.title represents the Label's text
configuration.title
.font(.headline)
.foregroundColor(.primary)
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(12)
}
}
// 2. Extension for easier use (Recommended)
extension LabelStyle where Self == VerticalLabelStyle {
static var vertical: VerticalLabelStyle {
VerticalLabelStyle()
}
}
How do we use this in Xcode?
struct ContentView: View {
var body: some View {
HStack(spacing: 20) {
Label("Home", systemImage: "house.fill")
Label("Messages", systemImage: "envelope.fill")
Label("Settings", systemImage: "gearshape.fill")
}
// We apply our custom style to the ENTIRE HStack
.labelStyle(.vertical)
}
}
In this example, instead of modifying the three labels one by one, the iOS Developer applies the modifier to the container. This is efficient and scalable Swift programming.
Example 2: Pill Label Style (PillLabelStyle)
Let’s create something more stylized, like a “badge” or tag you would see in an e-commerce or article categorization app.
struct PillLabelStyle: LabelStyle {
var backgroundColor: Color
func makeBody(configuration: Configuration) -> some View {
HStack(spacing: 6) {
configuration.icon
configuration.title
.fontWeight(.bold)
}
.font(.caption)
.foregroundColor(.white)
.padding(.symmetric, horizontal: 12, vertical: 6)
.background(backgroundColor)
.clipShape(Capsule())
}
}
extension LabelStyle where Self == PillLabelStyle {
static func pill(color: Color = .accentColor) -> PillLabelStyle {
PillLabelStyle(backgroundColor: color)
}
}
Implementation in the view:
struct CategoriesView: View {
var body: some View {
HStack {
Label("Swift", systemImage: "swift")
.labelStyle(.pill(color: .orange))
Label("Xcode", systemImage: "hammer.fill")
.labelStyle(.pill(color: .blue))
}
}
}
5. Cross-Platform Adaptability: iOS, macOS, and watchOS
One of the biggest promises of SwiftUI is “Learn once, apply anywhere.” As an iOS Developer who might also be developing for the Mac or the Apple Watch, labelStyle in SwiftUI becomes an indispensable tool for cross-platform code.
A. Usage on iOS
On iOS, touch interactions require generous tap targets. Labels are frequently used in Lists, where .automatic renders as titleAndIcon. However, in bottom Toolbars, the system often prefers to stack icons vertically above the text. By using Label instead of manual VStacks, you allow iOS to manage this transition automatically.
B. Usage on macOS (The Mac)
Swift programming for macOS has different paradigms. Users use a mouse or trackpad, so interfaces are denser.
In a List acting as a sidebar (Sidebar) in macOS, a Label will automatically adapt the font and icon size to the macOS Human Interface Guidelines (usually a smaller icon tinted with the app’s primary accent color).
If you try to compile a manual VStack in Xcode for macOS, it will look out of place. By using Label, SwiftUI knows exactly how to render it as a native Mac element.
C. Usage on watchOS
The Apple Watch screen is tiny. Here, space is at a premium. On watchOS, an iOS Developer often realizes that showing long text is counterproductive.
We can leverage conditional compilation or Size Classes to dynamically change our labelStyle in SwiftUI:
struct MultiplatformView: View {
#if os(watchOS)
let style = .iconOnly
#else
let style = .titleAndIcon
#endif
var body: some View {
Button(action: {
print("Training...")
}) {
Label("Start Workout", systemImage: "figure.walk")
}
.buttonStyle(.borderedProminent)
.labelStyle(style) // Adapts based on the operating system!
}
}
Note: Although this code works perfectly with #if os() compilation directives, in many SwiftUI cases, simply using the .automatic style and placing the label in a Toolbar on watchOS will let Apple decide to show only the icon for you. Less code to write in Xcode!
6. Integrating LabelStyle with Other Components
It is crucial for any iOS Developer to understand how Label interacts with interactive controls like Button, Toggle, or NavigationLink.
By default, the label of a Button in SwiftUI can be a Label.
Button {
// Save action
} label: {
Label("Save Document", systemImage: "square.and.arrow.down")
}
// We can apply the labelStyle directly to the button
.labelStyle(.iconOnly)
If you apply a labelStyle in SwiftUI that hides the text (.iconOnly) to a button, the button still knows what its title is. If you long-press that button on macOS or iPadOS, a native tooltip will appear with the text “Save Document”. This is pure Xcode and SwiftUI magic that you completely lose if you use a simple Image as your button design!
7. Advanced Use Cases: Leveraging @Environment
In advanced Swift programming, we might want our label style to react to changes in the environment (Environment), such as the color scheme (Dark/Light Mode) or dynamic text size (Dynamic Type).
Since the Configuration of the LabelStyle returns some View, we can inject environment variable reading into the style:
struct AdaptiveLabelStyle: LabelStyle {
@Environment(\.colorScheme) var colorScheme
@Environment(\.dynamicTypeSize) var dynamicTypeSize
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.icon
.imageScale(.large)
.foregroundColor(colorScheme == .dark ? .yellow : .blue)
// If the user uses a very large font size for accessibility,
// we can hide the text to avoid breaking the UI, or change the layout
if dynamicTypeSize < .accessibility1 {
configuration.title
.font(.body)
}
}
.padding(8)
}
}
This attention to detail distinguishes a good programmer from an excellent iOS Developer. Xcode makes it very easy to test these environment changes using Previews.
8. Best Practices when using Label and LabelStyle
To conclude this tutorial, here is a golden list of rules when working with these components in your Swift projects:
- Use
Labelwhenever possible: If you have an icon and text that represent a single logical idea, don’t useHStack { Image(); Text() }. UseLabel. It’s more semantic, more accessible, and easier to style. - Separate view design: If you find yourself adding
.font(),.foregroundColor(), and.padding()to multiple labels in the same view, stop. Create a customlabelStylein SwiftUI. Your code will be much cleaner. - Think about Accessibility: Rely on the
.titleOnlyor.iconOnlystyles instead of physically deleting the text or icon from your code. This ensures that VoiceOver always has descriptive text to read aloud. - Organize your styles: Create a separate file in Xcode (e.g.,
LabelStyles.swift) and group all yourLabelStyleextensions there. This will create a robust design library for your entire application. - Test on multiple platforms: If you are developing for the entire Apple ecosystem, use SwiftUI Previews to see how the
.automaticstyle reacts across different screen sizes and operating systems.
Conclusion
The labelStyle modifier in SwiftUI is much more than just a design tool; it is a bridge to a cleaner, more semantic, and cross-platform code architecture. As we’ve seen, from applying built-in styles to creating our own, mastering this component is an essential skill for any modern iOS Developer.
Swift programming has evolved dramatically, moving us away from micro-managing every pixel on the screen towards declaring intentions and design rules. By using Xcode and SwiftUI this way, you not only write less code, but you write better code, more future-proof and perfectly integrated with iOS, macOS, and watchOS.