- Published on
> Using SF Symbols in SwiftUI
- Authors

- Name
- Mick MacCallum
- @0x7fs
SF Symbols is Apple's library of over 5,000 vector icons designed to integrate seamlessly with San Francisco, the system font. They scale automatically with Dynamic Type, support multiple weights and rendering modes, and are available across all Apple platforms.
Basic Usage
Display an SF Symbol using Image(systemName:):
Image(systemName: "star.fill")
The symbol renders at a size that matches nearby text. To use it in a button or label:
Button {
// Action
} label: {
Label("Favorites", systemImage: "star.fill")
}
The Label view pairs text with an icon, automatically handling layout and accessibility.
Sizing Symbols
SF Symbols scale with font size. The easiest way to resize them is with the .font() modifier:
Image(systemName: "heart.fill")
.font(.largeTitle)
Image(systemName: "heart.fill")
.font(.system(size: 50))
For relative sizing within the current context, use .imageScale():
HStack {
Image(systemName: "star.fill")
.imageScale(.small)
Image(systemName: "star.fill")
.imageScale(.medium)
Image(systemName: "star.fill")
.imageScale(.large)
}
If you need pixel-precise control, make the symbol resizable:
Image(systemName: "star.fill")
.resizable()
.frame(width: 44, height: 44)
Coloring Symbols
Apply colors using .foregroundStyle():
Image(systemName: "heart.fill")
.foregroundStyle(.red)
Many symbols support multiple colors through hierarchical or palette rendering:
// Hierarchical - automatic opacity levels
Image(systemName: "square.stack.3d.up.fill")
.symbolRenderingMode(.hierarchical)
.foregroundStyle(.blue)
// Palette - explicit colors for each layer
Image(systemName: "person.crop.circle.badge.plus")
.symbolRenderingMode(.palette)
.foregroundStyle(.blue, .green)
Some symbols have built-in multicolor variants:
Image(systemName: "cloud.sun.rain.fill")
.symbolRenderingMode(.multicolor)
Symbol Weights
SF Symbols match font weights. Adjust the weight to match surrounding text:
HStack {
Text("Light")
.fontWeight(.light)
Image(systemName: "star.fill")
.fontWeight(.light)
}
HStack {
Text("Bold")
.fontWeight(.bold)
Image(systemName: "star.fill")
.fontWeight(.bold)
}
Symbol Variants
Many symbols have variants: filled, outlined, slashed, or with badges. Use the .symbolVariant() modifier:
Image(systemName: "heart")
.symbolVariant(.fill) // heart.fill
Image(systemName: "bell")
.symbolVariant(.slash) // bell.slash
Image(systemName: "folder")
.symbolVariant(.fill.badge.plus) // folder.fill.badge.plus
This approach is cleaner than manually constructing symbol names.
Animated Symbols (iOS 17+)
iOS 17 introduced symbol effects for animated transitions:
// Bounce effect
Image(systemName: "bell.fill")
.symbolEffect(.bounce, value: notificationCount)
// Pulse continuously
Image(systemName: "heart.fill")
.symbolEffect(.pulse)
// Variable color animation
Image(systemName: "wifi")
.symbolEffect(.variableColor.iterative)
For explicit control over when effects run:
struct AnimatedIcon: View {
@State private var isAnimating = false
var body: some View {
Image(systemName: "arrow.down.circle.fill")
.symbolEffect(.bounce, value: isAnimating)
.onTapGesture {
isAnimating.toggle()
}
}
}
Symbol Transitions
Animate changes between symbols:
struct PlayPauseButton: View {
@State private var isPlaying = false
var body: some View {
Button {
isPlaying.toggle()
} label: {
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
.contentTransition(.symbolEffect(.replace))
}
}
}
Finding the Right Symbol
Download the SF Symbols app from Apple to browse the complete library. You can search by name, category, or keyword. The app shows all variants and rendering modes for each symbol.
Common categories include:
- Communication (mail, phone, message)
- Weather (sun, cloud, rain)
- Objects (folder, doc, book)
- Devices (iphone, desktopcomputer, tv)
- Connectivity (wifi, antenna, network)
- Transportation (car, airplane, bicycle)
- Human (person, figure, hand)
- Nature (leaf, flame, drop)
Using Symbols in Labels and Buttons
The Label view is designed for symbol-text pairs:
Label("Settings", systemImage: "gear")
// Hide the text, keeping accessibility
Label("Settings", systemImage: "gear")
.labelStyle(.iconOnly)
// Hide the icon
Label("Settings", systemImage: "gear")
.labelStyle(.titleOnly)
In navigation and toolbars:
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
// Action
} label: {
Image(systemName: "plus")
}
}
}
Accessibility
SF Symbols used in Label or Button automatically get appropriate accessibility labels from the visible text. For standalone symbols, add your own:
Image(systemName: "xmark")
.accessibilityLabel("Close")
For decorative symbols that don't add meaning:
Image(systemName: "sparkles")
.accessibilityHidden(true)
Custom SF Symbols
You can create custom symbols that match the SF Symbols style using the SF Symbols app. Export a template, edit it in a vector editor, and import it back. Add the resulting SVG to your asset catalog with the "Symbol Image Set" type.
// Using a custom symbol from your asset catalog
Image("custom.symbol.name")
Custom symbols support the same features as system symbols: weights, scales, and rendering modes.
Tab Bar Icons
Tab bars work well with SF Symbols:
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profile", systemImage: "person")
}
}
The system automatically handles selected/unselected states and applies appropriate colors.
Platform Considerations
Most SF Symbols are available across iOS, macOS, watchOS, and tvOS, but some are platform-specific. The SF Symbols app shows availability for each symbol. When using a symbol that might not be available, you can provide a fallback:
if #available(iOS 16, *) {
Image(systemName: "shareplay")
} else {
Image(systemName: "person.2")
}
SF Symbols integrate naturally with SwiftUI and should be your first choice for icons. They're free, constantly updated by Apple, and automatically match system appearance and accessibility settings.
// Continue_Learning
Supporting Dark Mode in a SwiftUI App
Learn how to properly support dark mode in SwiftUI using semantic colors, adaptive color assets, and color scheme detection.
How to Add an Activity Indicator (Spinner) in SwiftUI
Learn how to show loading spinners in SwiftUI using ProgressView, including customization options and common loading patterns.
How to Resize an Image in SwiftUI
Learn how to resize images in SwiftUI using resizable(), frame(), and different content modes like scaledToFit and scaledToFill.
// Stay Updated
Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.