SF Pro: Variable Achsen, optische Größen und der Dynamic-Type-Vertrag
SF Pro, Apples Systemschrift seit iOS 9 / OS X El Capitan im Jahr 2015, ist eine Variable Font mit drei Achsen (Strichstärke, Breite, optische Größe), eine durchgestaltete Familie, die eine Sans-Serif (SF Pro), eine abgerundete Variante (SF Pro Rounded), eine Monospace (SF Mono), eine kompakte Variante (SF Compact, verwendet auf watchOS) und einen Serif-Begleiter (New York) umfasst1. Die Schrift ist um den Dynamic-Type-Vertrag herum konstruiert: Die elf Textstile von SwiftUI (.largeTitle, .title, .body, .callout, .footnote usw.) verwenden alle standardmäßig SF Pro, und sie skalieren alle automatisch, wenn der Benutzer seine bevorzugte Textgröße in den Einstellungen ändert.
Die meisten Apps verwenden ein oder zwei dieser elf Stile, ignorieren Dynamic Type über das Standardverhalten hinaus und rühren die variablen Achsen nie an. Das Ergebnis ist eine Typografie, die funktioniert, aber nicht das Vokabular der Plattform spricht. Der Beitrag durchläuft die Systemschriftfamilie, die variablen Achsen, die elf semantischen Stile, den Dynamic-Type-Vertrag und die Fälle, in denen benutzerdefinierte Schriften explizite Skalierungsarbeit benötigen, um teilzunehmen.
TL;DR
- SF Pro Variable stellt drei Achsen bereit: Strichstärke (
wght), Breite (wdth) und optische Größe (opsz)2. Die optische Größenanpassung erfolgt automatisch basierend auf der Punktgröße; Strichstärke und Breite sind über die SwiftUI-TypenFont.WeightundFont.Widthadressierbar. - Die Systemfamilie umfasst SF Pro (Standard), SF Pro Rounded (freundliche UI-Elemente), SF Mono (Code, technische UI), SF Compact (watchOS, schmale Kontexte) und New York (Serif-Begleiter für redaktionelle Lesetexte).
- Die elf Textstile von SwiftUI unterstützen Dynamic Type automatisch.
.bodyist der sichere Standard;.largeTitlebis.caption2decken die Hierarchie der Plattform ab. - Benutzerdefinierte Schriften skalieren standardmäßig nicht mit Dynamic Type. Verwenden Sie
Font.custom("Name", size: 16, relativeTo: .body), um die Schrift in die Dynamic-Type-Skalierung einzubinden3. @Environment(\.dynamicTypeSize)ermöglicht es einer View, das Layout an die aktuelle Textgröße anzupassen; der Wertebereich reicht von.xSmallbis.accessibility5(insgesamt 12 Größen)4.
Die Systemschriftfamilie
Apple liefert fünf Familien aus, die alle am Erlebnis der Systemschrift teilnehmen.
SF Pro
Der Standard für jede Apple-Plattform. iPhone, iPad, Mac und Vision verwenden SF Pro für Fließtext, Überschriften und den Großteil der UI. Die Schrift hat eine breite Sprachabdeckung (Lateinisch, Griechisch, Kyrillisch, Arabisch, Hebräisch, Devanagari usw.), unterstützt von Haus aus Right-to-Left-Layouts und enthält gestaltete Varianten für Kapitälchen, alternative Ziffern (Versal- vs. Tabellenziffern) und stilistische Alternativen.
Zugriff in SwiftUI über die Systemschrift:
Text("Hello").font(.system(.body)) // SF Pro by default
Text("Hello").font(.system(.body, weight: .semibold)) // SF Pro Semibold
Text("Hello").font(.system(.body, design: .default)) // explicit SF Pro
SF Pro Rounded
Eine abgerundete Variante, gestaltet für freundliche, zugängliche UI: Apple-Watch-Komplikationen, Fitness-Ringe, Teile der Richtungs-Callouts in Karten, Wo ist? und ausgewählte Health-Oberflächen. Die abgerundeten Formen kommunizieren Weichheit; verwenden Sie sie für den Tonfall, nicht nur für visuelle Abwechslung.
Text("Hello").font(.system(.body, design: .rounded))
SF Mono
Die Monospace-Familie für Code, Terminal-UI und jeden Kontext, in dem die Ausrichtung von Zeichenzellen wichtig ist. SF Mono ist standardmäßig die Schrift in Xcode, in der Monospace-Einstellung der Terminal-App und in jeder SwiftUI-View, die .monospaced anfordert.
Text("let x = 42").font(.system(.body, design: .monospaced))
SF Compact
Eine schmalere Familie, die auf watchOS, bei tvOS-Fokus-Hervorhebungen und in einigen Mac-Kontexten verwendet wird, in denen der horizontale Raum begrenzt ist. Die schmaleren Formen erhalten die x-Höhe, während sie den horizontalen Vorschub reduzieren, wodurch sie in den Dimensionen von Apple-Watch-Zifferblättern funktionieren, in denen sich SF Pro beengt anfühlen würde.
watchOS-Apps verwenden über die Systemschrift automatisch SF Compact; iOS-Apps müssen sie in der Regel nicht explizit anfordern.
New York
Eine Serif-Familie, die als Begleiter für redaktionelles Lesen gestaltet wurde. New York erscheint in Bücher für Langtexte, in Notizen für handschriftähnliche Notizen und in SwiftUI über das Design .serif.
Text("Long-form essay").font(.system(.body, design: .serif))
Der Serif-Begleiter ist in App-UI selten. Greifen Sie bewusst danach (für einen Lesemodus, eine zitierte Passage, einen Artikeltext) und nicht als Standard.
Die drei variablen Achsen
SF Pro Variable kodiert drei Achsen, die sich kombinieren, um jede Glyphe zu erzeugen:
Strichstärke (wght)
Neun benannte Strichstärken: .ultraLight, .thin, .light, .regular, .medium, .semibold, .bold, .heavy, .black. Die Variable Font interpoliert kontinuierlich zwischen ihnen, aber API von SwiftUI stellt die benannten Werte bereit.
Text("Heading").font(.system(.title, weight: .semibold))
Strichstärke kommuniziert die Gewichtungshierarchie: .regular für Fließtext, .semibold oder .bold für Überschriften, .medium für aktive Toolbar-Elemente, .light für entkräftigte Beschriftungen. Die semantischen Stile (.headline, .subheadline) werden mit sinnvollen Strichstärken-Standardwerten ausgeliefert; greifen Sie nur dann zu expliziten Strichstärken, wenn der semantische Stil nicht die richtige Form hat.
Breite (wdth)
Vier benannte Breiten in API ab iOS 16: .compressed, .condensed, .standard, .expanded. Die Breitenachse beeinflusst den horizontalen Vorschub, ohne Strichstärke oder visuellen Charakter zu verändern. Verwenden Sie sie für enge UI (eine Navigationsleiste mit vielen Elementen) oder für visuelle Textur (eine Überschrift in Display-Größe, die mehr horizontale Präsenz haben soll).
Die Breite wird über den View-Modifikator .fontWidth(_:) von SwiftUI angewendet (oder an einer Font über .width(_:) verkettet):
Text("Compressed")
.font(.system(.title, weight: .bold))
.fontWidth(.compressed)
Die Breite ist selten die richtige Achse für Fließtext; sie funktioniert gut bei Display-Größen, in denen die Typografie Teil des Designs ist.
Optische Größe (opsz)
Die technisch ambitionierteste Achse. Die alten Varianten SF Text und SF Display von SF Pro sind jetzt ein kontinuierlicher Verlauf, der in der Variable Font kodiert ist. Bei Größen unter 20 Punkt wendet das System die optischen Anpassungen von SF Text an (breitere Buchstabenabstände, etwas schwerere Striche, offenere Punzen). Über 20 Punkt übernimmt SF Display (engere Abstände, verfeinerte Proportionen). Der Übergang ist fließend.
Die Achse opsz ist automatisch. Apps adressieren sie nicht explizit; das System liest die angeforderte Punktgröße aus und löst sie zur passenden optischen Größe auf. Die Konsequenz: Typografie in kleinen UI-Größen hat andere Proportionen als dieselbe Schrift in Überschriftengrößen, und das ist so beabsichtigt. Benutzerdefinierte Schriften ohne optische Größenanpassung sehen in einer Größe gut und in anderen falsch aus; die automatische Handhabung von SF Pro vermeidet diese Falle vollständig.
Die elf Textstile
Font.TextStyle von SwiftUI definiert elf semantische Stile, die alle an Dynamic Type teilnehmen4:
| Stil | Standardgröße (Large) | Häufige Verwendung |
|---|---|---|
.largeTitle |
34 pt | Überschriften der obersten Ebene, Hero-Text |
.title |
28 pt | Abschnittsüberschriften |
.title2 |
22 pt | Unterabschnittsüberschriften |
.title3 |
20 pt | Kleinere Überschriften |
.headline |
17 pt | Hervorgehobener Fließtext, Titel von Listenzeilen |
.body |
17 pt | Standard-Fließtext |
.callout |
16 pt | Unterstützender Fließtext, Bildunterschriften im Kontext |
.subheadline |
15 pt | Sekundäre Überschriften, Meta-Text |
.footnote |
13 pt | Kleiner unterstützender Text |
.caption |
12 pt | Bildunterschriften, Kleingedrucktes |
.caption2 |
11 pt | Kleinster lesbarer Text |
Die Spalte „Standardgröße” zeigt die Größe bei der Dynamic-Type-Einstellung „Large” des Benutzers (der Systemstandard). Jeder Stil skaliert nach oben oder unten, wenn der Benutzer seine bevorzugte Textgröße anpasst; die relative Hierarchie bleibt erhalten.
Der richtige Adoptionsschritt ist, die semantischen Stile direkt zu verwenden:
VStack(alignment: .leading) {
Text("Title").font(.title)
Text("Subtitle").font(.subheadline).foregroundStyle(.secondary)
Text("Body content here.").font(.body)
}
Die Hierarchie bleibt bei jeder Dynamic-Type-Einstellung erhalten, die Konventionen der Apple HIG werden eingehalten, und die Typografie reagiert ohne app-spezifischen Code auf die Barrierefreiheits-Voreinstellungen des Benutzers.
Der Dynamic-Type-Vertrag
Dynamic Type ist die vom Benutzer kontrollierte Textgrößen-Einstellung unter Einstellungen > Bedienungshilfen > Anzeige & Textgröße > Größerer Text. Der Wert fließt über die Umgebung als DynamicTypeSize mit zwölf Werten von .xSmall bis .accessibility54:
- Standardgrößen:
.xSmall,.small,.medium,.large(Standard),.xLarge,.xxLarge,.xxxLarge - Barrierefreiheitsgrößen:
.accessibility1,.accessibility2,.accessibility3,.accessibility4,.accessibility5
Apps, die die semantischen Textstile verwenden, erhalten die Skalierung kostenlos. Apps, die das Layout an die aktuelle Größe anpassen möchten, lesen die Umgebung aus:
struct AdaptiveLayout: View {
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var body: some View {
if dynamicTypeSize.isAccessibilitySize {
VStack { content } // stack vertically at accessibility sizes
} else {
HStack { content } // horizontal at standard sizes
}
}
}
Die Eigenschaft isAccessibilitySize deckt die fünf Barrierefreiheitsgrößen ab (bei denen der Text groß genug ist, dass horizontale Layouts oft umbrechen). Das Muster ist das richtige für jedes Layout, das davon abhängt, dass Text horizontal passt.
Apps können den unterstützten Bereich mit dem Modifikator .dynamicTypeSize(_:) einschränken:
ContentView()
.dynamicTypeSize(.large ... .accessibility3)
Die Einschränkung kappt die Dynamic-Type-Einstellung für den modifizierten Teilbaum. Verwenden Sie sie, wenn das Layout einer View den vollen Bereich tatsächlich nicht aufnehmen kann; der richtige Standard ist es, jede Größe zu unterstützen und stattdessen das Layout anzupassen.
Benutzerdefinierte Schriften und Dynamic Type
Benutzerdefinierte Schriften (eine Markenschrift, die über das Array UIAppFonts in der Info.plist ausgeliefert wird) skalieren standardmäßig nicht mit Dynamic Type. Die einfachste Lösung ist der Parameter relativeTo: von Font.custom:
// Doesn't scale with Dynamic Type
Text("Brand").font(.custom("MyBrandFont", size: 16))
// Scales with Dynamic Type relative to body
Text("Brand").font(.custom("MyBrandFont", size: 16, relativeTo: .body))
Der Parameter relativeTo: weist SwiftUI an, die benutzerdefinierte Schrift mithilfe der Skalierungskurve des Body-Stils zu skalieren. Die Schriftgröße bei der „Large”-Einstellung des Benutzers ist die angeforderten 16 pt; bei größeren Einstellungen wendet SwiftUI denselben Multiplikator an, den der Body-Stil verwenden würde.
Für anspruchsvollere Skalierung (unterschiedliche Kurven bei unterschiedlichen Größen, benutzerdefinierte optische Handhabung) verwenden Sie UIFontMetrics von UIKit direkt. Das Muster ist ausführlicher, unterstützt aber pro Größe vorgenommene Anpassungen, die benutzerdefinierte Schriften häufig benötigen.
Wenn Typografie versagt
Drei Fehlermodi, die es zu benennen lohnt:
Überall festgrößte benutzerdefinierte Schriften. Der häufigste Barrierefreiheitsfehler von iOS-Apps: Eine Markenschrift, die mit Font.custom("BrandFont", size: 16) (ohne relativeTo:) ausgeliefert wird, ignoriert Dynamic Type vollständig. Benutzer mit Barrierefreiheits-Textgrößen sehen Markentext mit 16 pt, während Systemtext auf 28 pt+ skaliert; die visuelle Hierarchie kehrt sich um. Die Lösung ist relativeTo: bei jeder Verwendung benutzerdefinierter Schriften, geprüft über den AccessibilityInspector bei maximaler Dynamic-Type-Einstellung.
Hartkodierte Strichstärken zur Hervorhebung. Ein Untertitel, der mit .font(.body).fontWeight(.bold) gestaltet ist, ist fragil: Bei Barrierefreiheitsgrößen wird der fette Body-Text fast nicht mehr von einem ohnehin schon großen Body-Text zu unterscheiden sein. Der semantische Stil .headline handhabt die Hervorhebung über den gesamten Dynamic-Type-Bereich korrekt; verwenden Sie ihn anstelle von Body+Fett.
Layouts, die bei Barrierefreiheitsgrößen brechen. Ein horizontaler Stack aus Text + Icon + Text, der bei .accessibility3 überläuft, ist ein Layout-Bug, den Dynamic Type aufdeckt. Die Lösung ist das oben genannte adaptive Layout-Muster mit dynamicTypeSize.isAccessibilitySize; der Test besteht darin, die App während der QA bei maximalem Dynamic Type laufen zu lassen, nicht nur bei der Standardgröße.
Was dieses Muster für iOS-26+-Apps bedeutet
Drei Erkenntnisse.
-
Verwenden Sie die semantischen Textstile, keine handabgestimmten Punktgrößen.
.body,.headline,.title2usw. tragen Dynamic Type, optische Größenanpassung und plattformkonforme Hierarchie. HandabgestimmtesFont.system(size: 17)hebelt jede Systemfunktion aus und altert schlecht, wenn Apple die Standardrampe anpasst. -
Übergeben Sie immer
relativeTo:bei benutzerdefinierten Schriften. Eine Markenschrift, die mitFont.custom(_, size: _, relativeTo: .body)ausgeliefert wird, nimmt an Dynamic Type teil. Eine Markenschrift, die ohne ausgeliefert wird, ist eine Barrierefreiheits-Regression pro Benutzer, die die QA nur bei maximaler Textgröße entdecken wird. -
Testen Sie Layouts bei Dynamic-Type-Größen für Barrierefreiheit. Die Einstellung
.accessibility3ist etwa das Doppelte der Large-Standardeinstellung. Layouts, die bei Standardgrößen gut aussehen, brechen bei Barrierefreiheitsgrößen routinemäßig. Die Lösung ist die Anpassung auf Layout-Ebene über die UmgebungdynamicTypeSizeund nicht der Ausstieg über.dynamicTypeSize(...)-Einschränkungen.
Der vollständige Apple-Ecosystem-Cluster: typisierte App Intents; MCP-Server; die Routing-Frage; Foundation Models; die Unterscheidung zwischen Laufzeit und Tooling-LLM; drei Oberflächen; das Single-Source-of-Truth-Muster; Zwei MCP-Server; Hooks für die Apple-Entwicklung; Live Activities; der watchOS-Laufzeitvertrag; SwiftUI-Interna; das räumliche mentale Modell von RealityKit; SwiftData-Schema-Disziplin; Liquid-Glass-Muster; Multi-Plattform-Auslieferung; die Plattform-Matrix; Vision-Framework; Symbol Effects; Core-ML-Inferenz; Writing Tools API; Swift Testing; Privacy Manifest; Barrierefreiheit als Plattform; worüber ich mich weigere zu schreiben. Der Hub befindet sich bei der Apple Ecosystem Series. Für einen breiteren Kontext zu iOS mit AI-Agenten siehe den iOS Agent Development Guide.
FAQ
Was ist der Unterschied zwischen SF Pro und SF Pro Display / SF Pro Text?
Von iOS 9 (als SF erstmals als Systemschrift ausgeliefert wurde) bis iOS 16 wurde SF als zwei separate Schriften ausgeliefert: SF Text für Größen unter 20 pt und SF Display für Größen ab 20 pt, jeweils mit handabgestimmten Buchstabenabständen und Strichstärken für ihren Größenbereich. SF Pro Variable konsolidiert dieselbe Aufteilung in Text/Display in einer kontinuierlichen Achse für die optische Größe (opsz). Die beiden Schriften sind nicht mehr getrennt; die Variable Font behandelt den Übergang automatisch basierend auf der angeforderten Punktgröße.
Wie erhalte ich Monospace-Ziffern in Fließtext?
Verwenden Sie .monospacedDigit() in SwiftUI:
Text("\(score)").font(.body).monospacedDigit()
Der Modifikator tauscht die proportionalen Ziffern der Body-Schrift gegen Monospace-Ziffern aus, während der Rest des Textes proportional bleibt. Verwenden Sie ihn für jede UI, in der Ziffern über Zeilen hinweg ausgerichtet sein müssen (Timer, Punktetafeln, Saldoanzeigen).
Sollte ich SF Pro Rounded für die gesamte UI verwenden?
Nein. SF Pro Rounded trägt einen Tonfall (freundlich, zugänglich), der zu manchen Kontexten passt und zu anderen nicht. Die Komplikationen der Watch-App, das Telefonnummern-Tastenfeld des iPhones und bestimmte Oberflächen der Health-App verwenden ihn. Eine Produktivitäts-App, eine Banking-App oder ein Entwicklerwerkzeug sollte das in der Regel nicht. Greifen Sie bewusst zu .rounded, nicht als Standard.
Was ist der richtige Dynamic-Type-Bereich für eine iPhone-App?
Standardmäßig sollten Sie jede Größe von .xSmall bis .accessibility5 unterstützen. Die Barrierefreiheitsgrößen (.accessibility1 bis .accessibility5) sind die Art und Weise, wie Benutzer mit Sehschwäche, motorischen Einschränkungen oder anderen Barrierefreiheitsbedürfnissen das iPhone verwenden. Eine App, die über .dynamicTypeSize(...)-Einschränkungen aussteigt, lässt diese Benutzer im Stich. Der richtige Schritt ist die Layout-Anpassung (das isAccessibilitySize-Muster) und nicht der Ausstieg aus dem Größenbereich.
Kann ich mit meiner App eine benutzerdefinierte Variable Font ausliefern?
Ja. Variable Fonts werden wie jede andere benutzerdefinierte Schrift ausgeliefert (zur UIAppFonts in der Info.plist hinzufügen, über Font.custom referenzieren). Um die variablen Achsen aus SwiftUI heraus anzusprechen, verwenden Sie die zugrunde liegenden CTFont-APIs von Font.custom über UIFontDescriptor.SymbolicTraits oder, für die volle Achsenkontrolle, steigen Sie zu CTFontCreateCopyWithAttributes mit kCTFontVariationAttribute ab. Die Brücke von SwiftUI zu variablen Achsen ist ausführlicher als bei Systemschriften; für die meisten Apps decken Systemschriften die Fälle ab.
Quellen
-
Apple Developer: Fonts. Übersicht über die Systemschriftfamilie einschließlich SF Pro, SF Pro Rounded, SF Mono, SF Compact und New York. ↩
-
Apple Developer: Meet the expanded San Francisco font family (WWDC 2022 Session 110381). Die Einführung des dreiachsigen Designs von SF Pro Variable (Strichstärke, Breite, optische Größe). ↩
-
Apple Developer Documentation:
Font.custom(_:size:relativeTo:). Der Initialisierer für benutzerdefinierte Schriften, der die Schrift in die Dynamic-Type-Skalierung relativ zu einem gewählten Textstil einbindet. ↩ -
Apple Developer Documentation:
DynamicTypeSize. Das Enum mit zwölf Werten von.xSmallbis.accessibility5plus dem PrädikatisAccessibilitySizefür die Anpassung auf Layout-Ebene. ↩↩↩