Responsive Typografie und flexible Größen
Responsive Typografie passt Schriftgrößen, Zeilenlängen und Abstände an den
verfügbaren Platz an. Texte sollen auf kleinen und großen Bildschirmen gut
lesbar bleiben, ohne dass für jede Viewport-Breite eine eigene Media Query
erforderlich ist.
Dafür stehen unter anderem relative Einheiten wie rem,
em und vw sowie die CSS-Funktionen
calc(), min(), max() und
clamp() zur Verfügung.
Absolute und relative Einheiten
CSS unterscheidet zwischen absoluten und relativen Längeneinheiten.
Absolute Einheiten besitzen einen festen Bezug, während relative Einheiten
von einer anderen Größe abhängig sind.
| Einheit |
Art |
Bezug |
px |
absolut |
CSS-Pixel |
% |
relativ |
Abhängig von der jeweiligen Eigenschaft |
em |
relativ |
Schriftgröße des Elements oder des übergeordneten Elements |
rem |
relativ |
Schriftgröße des Wurzelelements <html> |
vw |
relativ |
Ein Prozent der Viewport-Breite |
vh |
relativ |
Ein Prozent der Viewport-Höhe |
vmin |
relativ |
Ein Prozent der kleineren Viewport-Abmessung |
vmax |
relativ |
Ein Prozent der größeren Viewport-Abmessung |
ch |
relativ |
Ungefähr die Breite des Zeichens „0“ der verwendeten Schrift |
cqi |
relativ |
Ein Prozent der Inline-Größe eines Query Containers |
Schriftgrößen mit rem
Die Einheit rem bezieht sich auf die berechnete Schriftgröße
des Wurzelelements <html>.
html {
font-size: 100%;
}
body {
font-size: 1rem;
}
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
}
.small-text {
font-size: 0.875rem;
}
Bei der üblichen Grundeinstellung des Browsers entsprechen
1rem normalerweise 16px. Die tatsächliche Größe
kann jedoch durch Browser- und Benutzereinstellungen verändert werden.
Die Angabe font-size: 100% auf dem
<html>-Element übernimmt die bevorzugte
Standardschriftgröße des Browsers.
Der Unterschied zwischen em und rem
.card {
font-size: 1.25rem;
padding: 1em;
}
.card-title {
font-size: 1.5em;
}
Bei font-size bezieht sich em auf die
Schriftgröße des übergeordneten Elements. Bei anderen Eigenschaften bezieht
es sich normalerweise auf die eigene berechnete Schriftgröße.
| Einheit |
Typischer Einsatz |
rem |
Einheitliche Schriftgrößen und Abstände mit Bezug auf das
Wurzelelement
|
em |
Abstände und Größen, die gemeinsam mit der lokalen Schriftgröße
wachsen oder schrumpfen sollen
|
Verschachtelte Schriftgrößen in em können sich vervielfachen.
Bei tief verschachtelten Elementen ist deshalb besondere Aufmerksamkeit
erforderlich.
Verschachtelung mit em
.list {
font-size: 1.2em;
}
.list .list {
font-size: 1.2em;
}
Eine verschachtelte Liste übernimmt zunächst die vergrößerte Schriftgröße
der äußeren Liste und vergrößert diese anschließend erneut. Dadurch können
unerwartet große Texte entstehen.
Mit rem bleibt der Bezug dagegen gleich:
.list {
font-size: 1.2rem;
}
.list .list {
font-size: 1.2rem;
}
Typografische Grundeinstellungen
body {
margin: 0;
color: #343a40;
font-family:
system-ui,
-apple-system,
"Segoe UI",
sans-serif;
font-size: 1rem;
line-height: 1.6;
}
Eine gut lesbare Grundschrift benötigt neben einer geeigneten Schriftgröße
auch ausreichend Zeilenabstand und einen guten Kontrast zum Hintergrund.
-
font-size bestimmt die grundlegende Größe der Schrift.
-
line-height bestimmt den Abstand zwischen den Textzeilen.
-
font-family legt die verwendete Schriftfamilie fest.
-
color muss einen ausreichenden Kontrast zum Hintergrund
besitzen.
Zeilenhöhe ohne Einheit
body {
line-height: 1.6;
}
h1,
h2,
h3 {
line-height: 1.2;
}
Eine einheitenlose Zeilenhöhe wird mit der jeweiligen Schriftgröße des
Elements multipliziert. Untergeordnete Elemente erben dadurch den Faktor
und können ihre Zeilenhöhe passend zur eigenen Schriftgröße berechnen.
Für längere Fließtexte sind Werte zwischen ungefähr
1.5 und 1.7 häufig ein guter Ausgangspunkt.
Der passende Wert hängt jedoch auch von Schriftart, Schriftgröße und
Zeilenlänge ab.
Lesbare Zeilenlänge mit ch
.text-content {
width: min(100%, 70ch);
margin-inline: auto;
}
Sehr lange Textzeilen erschweren das Wiederfinden des Zeilenanfangs.
Mit der Einheit ch kann die maximale Breite eines Textbereichs
ungefähr anhand der Zeichenbreite begrenzt werden.
Für längere Fließtexte sind ungefähr 45 bis 75 Zeichen pro Zeile häufig
gut lesbar. Dies ist ein Richtwert und keine feste technische Vorgabe.
Viewport-Einheiten
.hero-title {
font-size: 6vw;
}
Die Einheit vw reagiert direkt auf die Breite des Viewports.
6vw entsprechen sechs Prozent der Viewport-Breite.
Eine ausschließlich mit vw definierte Schrift kann auf kleinen
Viewports zu klein und auf sehr großen Viewports zu groß werden.
Viewport-Einheiten sollten bei Schriftgrößen normalerweise mit sinnvollen
Mindest- und Höchstwerten begrenzt werden.
Moderne Viewport-Einheiten
Auf mobilen Geräten kann sich die sichtbare Höhe verändern, wenn die
Adress- oder Werkzeugleiste ein- und ausgeblendet wird. Dafür gibt es
unterschiedliche Varianten der Viewport-Einheiten.
| Einheit |
Bedeutung |
svh |
Ein Prozent der kleinen Viewport-Höhe bei eingeblendeten
Browser-Bedienelementen
|
lvh |
Ein Prozent der großen Viewport-Höhe bei ausgeblendeten
Browser-Bedienelementen
|
dvh |
Ein Prozent der aktuell sichtbaren dynamischen Viewport-Höhe
|
svw |
Ein Prozent der kleinen Viewport-Breite |
lvw |
Ein Prozent der großen Viewport-Breite |
dvw |
Ein Prozent der dynamischen Viewport-Breite |
.hero {
min-height: 100svh;
}
.fullscreen-dialog {
min-height: 100dvh;
}
Berechnungen mit calc()
Mit calc() können Werte und unterschiedliche kompatible
Einheiten miteinander verrechnet werden.
.content {
width: calc(100% - 2rem);
}
.sidebar {
height: calc(100vh - 5rem);
}
.title {
font-size: calc(1.5rem + 1vw);
}
Um die mathematischen Operatoren sollten Leerzeichen stehen. Das ist
besonders bei Addition und Subtraktion erforderlich.
| Operator |
Bedeutung |
+ |
Addition |
- |
Subtraktion |
* |
Multiplikation |
/ |
Division |
Den kleineren Wert mit min() auswählen
.content {
width: min(100% - 2rem, 75rem);
margin-inline: auto;
}
min() verwendet den kleinsten der angegebenen Werte. Der
Inhaltsbereich wird dadurch höchstens 75rem breit, behält auf
schmaleren Viewports aber einen seitlichen Abstand.
Eine weitere mögliche Schreibweise ist:
.text-content {
width: min(100%, 70ch);
}
Den größeren Wert mit max() auswählen
.section {
padding-inline: max(1rem, 5vw);
}
max() verwendet den größten der angegebenen Werte. Der seitliche
Abstand beträgt dadurch mindestens 1rem und kann auf breiteren
Viewports mit 5vw wachsen.
.card {
width: max(18rem, 40%);
}
Ein großer Mindestwert kann auf schmalen Viewports zu einem horizontalen
Überlauf führen. Der verfügbare Platz muss deshalb berücksichtigt werden.
Werte mit clamp() begrenzen
clamp() verbindet einen Mindestwert, einen bevorzugten Wert
und einen Höchstwert.
.title {
font-size: clamp(2rem, 5vw, 4rem);
}
Die Funktion besitzt drei Argumente:
clamp(Mindestwert, bevorzugter Wert, Höchstwert)
| Wert |
Aufgabe |
2rem |
Die Schrift wird nicht kleiner als 2rem. |
5vw |
Innerhalb der Grenzen reagiert die Schrift auf die
Viewport-Breite.
|
4rem |
Die Schrift wird nicht größer als 4rem. |
Fließende Schriftgrößen mit clamp()
h1 {
font-size: clamp(2rem, 1.4rem + 3vw, 4.5rem);
}
h2 {
font-size: clamp(1.6rem, 1.25rem + 1.75vw, 3rem);
}
h3 {
font-size: clamp(1.25rem, 1.1rem + 0.75vw, 1.75rem);
}
Der bevorzugte Wert verbindet eine feste Grundgröße mit einem flexiblen
Viewport-Anteil. Dadurch wächst die Schrift gleichmäßiger als bei einer
reinen vw-Angabe.
Die Mindest- und Höchstwerte sollten so gewählt werden, dass die Texte auch
bei starkem Zoom und auf sehr schmalen oder breiten Viewports gut lesbar
bleiben.
Flexible Abstände mit clamp()
.section {
padding-block: clamp(2rem, 6vw, 6rem);
padding-inline: clamp(1rem, 4vw, 3rem);
}
.card-grid {
gap: clamp(1rem, 3vw, 2.5rem);
}
Nicht nur Schriftgrößen, sondern auch Innenabstände, Außenabstände und
Zwischenräume können fließend an den verfügbaren Platz angepasst werden.
Ein flexibles Größen- und Abstandssystem
:root {
--font-size-small: clamp(0.875rem, 0.84rem + 0.15vw, 1rem);
--font-size-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--font-size-h3: clamp(1.25rem, 1.1rem + 0.75vw, 1.75rem);
--font-size-h2: clamp(1.6rem, 1.3rem + 1.5vw, 2.75rem);
--font-size-h1: clamp(2rem, 1.4rem + 3vw, 4.5rem);
--space-small: clamp(0.5rem, 0.35rem + 0.75vw, 1rem);
--space-medium: clamp(1rem, 0.7rem + 1.5vw, 2rem);
--space-large: clamp(2rem, 1.25rem + 3.75vw, 5rem);
}
body {
font-size: var(--font-size-base);
}
h1 {
font-size: var(--font-size-h1);
}
h2 {
font-size: var(--font-size-h2);
}
section {
padding-block: var(--space-large);
}
.card-grid {
gap: var(--space-medium);
}
Custom Properties erleichtern es, wiederkehrende Schriftgrößen und Abstände
einheitlich zu verwalten.
Container-relative Typografie
Innerhalb wiederverwendbarer Komponenten kann sich die Typografie an der
Größe des Query Containers statt an der Größe des gesamten Viewports
orientieren.
.card-wrapper {
container: card / inline-size;
}
.card-title {
font-size: clamp(1.25rem, 6cqi, 2rem);
}
cqi entspricht einem Prozent der Inline-Größe des Query
Containers. In einer horizontalen Schreibweise ist dies normalerweise die
Breite des Containers.
Container-relative Schriftgrößen sollten mit clamp() begrenzt
werden, damit sie weder zu klein noch unverhältnismäßig groß werden.
Text auf kleinen Viewports umbrechen
h1,
h2,
h3 {
overflow-wrap: break-word;
}
.long-url {
overflow-wrap: anywhere;
}
Lange Wörter, Dateinamen oder URLs können aus einem schmalen Container
herausragen. Mit overflow-wrap kann der Browser bei Bedarf
zusätzliche Umbruchstellen verwenden.
| Wert |
Wirkung |
normal |
Verwendet die normalen Umbruchregeln. |
break-word |
Darf lange Wörter umbrechen, wenn sie sonst den Container
überschreiten.
|
anywhere |
Erlaubt bei Bedarf einen Umbruch an praktisch jeder Stelle und
berücksichtigt diese Möglichkeiten bei der Größenberechnung.
|
Automatische Silbentrennung
.text-content {
hyphens: auto;
}
Mit hyphens: auto kann der Browser Wörter entsprechend der
angegebenen Dokumentsprache automatisch trennen.
<html lang="de">
Die korrekte Angabe des lang-Attributs ist für die
sprachabhängige Silbentrennung besonders wichtig.
Die tatsächliche Silbentrennung hängt von Browser, Sprache und verfügbarem
Wörterbuch ab.
Überschriften ausgewogen umbrechen
h1,
h2 {
text-wrap: balance;
}
text-wrap: balance versucht, mehrzeilige Überschriften
gleichmäßiger auf die vorhandenen Zeilen zu verteilen.
.intro {
text-wrap: pretty;
}
text-wrap: pretty kann bei Fließtext ungünstige Umbrüche,
beispielsweise ein einzelnes kurzes Wort in der letzten Zeile, reduzieren.
Die Eigenschaften verbessern den Umbruch, ersetzen aber keine sinnvoll
gewählte Textbreite.
Text nicht durch feste Höhen abschneiden
.card-content {
min-height: 12rem;
}
Eine Mindesthöhe darf überschritten werden, wenn der Inhalt mehr Platz
benötigt. Eine feste Höhe kann dagegen bei größerer Schrift, längerem Text
oder stärkerem Zoom zum Abschneiden des Inhalts führen.
/* Problematisch */
.card-content {
height: 12rem;
overflow: hidden;
}
Textbereiche sollten normalerweise keine feste Höhe erhalten, wenn die
Textmenge oder die vom Benutzer eingestellte Schriftgröße variieren kann.
Benutzerzoom und Barrierefreiheit
Benutzerinnen und Benutzer können die Browserdarstellung oder die
Standardschriftgröße vergrößern. Ein responsives Layout muss auch bei
vergrößertem Text nutzbar bleiben.
-
Die Standardschriftgröße des Browsers sollte nicht durch eine sehr kleine
feste Pixelgröße ersetzt werden.
-
Inhalte dürfen bei Textvergrößerung nicht abgeschnitten werden.
-
Navigationen und Schaltflächen müssen umbrechen oder ausreichend Platz
erhalten.
-
Text sollte nicht ausschließlich durch
overflow: hidden verborgen werden.
-
Feste Höhen sollten für Bereiche mit Text vermieden werden.
-
Horizontales Scrollen sollte bei normalem Seiteninhalt möglichst nicht
erforderlich sein.
Relative Einheiten unterstützen flexible Layouts. Entscheidend ist jedoch
immer, dass das Ergebnis bei unterschiedlichen Schriftgrößen und Zoomstufen
tatsächlich geprüft wird.
Ein vollständiges Beispiel
:root {
--font-size-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--font-size-h1: clamp(2rem, 1.4rem + 3vw, 4.5rem);
--font-size-h2: clamp(1.5rem, 1.2rem + 1.5vw, 2.75rem);
--space-small: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
--space-medium: clamp(1rem, 0.7rem + 1.5vw, 2rem);
--space-large: clamp(2rem, 1.25rem + 3.75vw, 5rem);
}
body {
margin: 0;
color: #343a40;
font-family:
system-ui,
-apple-system,
"Segoe UI",
sans-serif;
font-size: var(--font-size-base);
line-height: 1.6;
}
.page-wrapper {
width: min(100% - 2rem, 75rem);
margin-inline: auto;
}
.hero {
padding-block: var(--space-large);
}
.hero-title {
max-width: 18ch;
margin-block: 0 var(--space-medium);
font-size: var(--font-size-h1);
line-height: 1.05;
overflow-wrap: break-word;
text-wrap: balance;
}
.hero-text {
max-width: 65ch;
margin: 0;
font-size: clamp(1.05rem, 1rem + 0.5vw, 1.35rem);
text-wrap: pretty;
}
.content-section {
padding-block: var(--space-large);
}
.content-section h2 {
max-width: 25ch;
font-size: var(--font-size-h2);
line-height: 1.2;
text-wrap: balance;
}
.content-section p {
max-width: 70ch;
}
Das Beispiel kombiniert:
- fließende Schriftgrößen mit
clamp()
- flexible Abstände mit Custom Properties
- eine begrenzte Seitenbreite mit
min()
- lesbare Zeilenlängen mit
ch
- einheitenlose Zeilenhöhen
- verbesserte Umbrüche für Überschriften und Fließtexte
Häufige Fehler
-
Sehr kleine feste Schriftgrößen erschweren die Lesbarkeit.
-
Schriftgrößen werden ausschließlich mit
vw definiert und
dadurch auf schmalen Viewports zu klein oder auf breiten Viewports zu
groß.
-
clamp() wird ohne sinnvolle Mindest- und Höchstwerte
verwendet.
-
Verschachtelte
em-Schriftgrößen vergrößern oder verkleinern
sich unbeabsichtigt mehrfach.
-
Fließtext erstreckt sich über die gesamte Breite eines großen Bildschirms.
-
Eine zu kleine Zeilenhöhe erschwert das Lesen längerer Texte.
-
Textcontainer besitzen feste Höhen und schneiden vergrößerte Inhalte ab.
-
Lange URLs oder Wörter verursachen horizontalen Überlauf.
-
Bei automatischer Silbentrennung fehlt die korrekte Sprache im
lang-Attribut.
-
Abstände und Schriftgrößen wachsen unbegrenzt mit dem Viewport.
-
Das Layout wird nicht mit vergrößerter Schrift oder Browserzoom geprüft.
Zusammenfassung
-
rem bezieht sich auf die Schriftgröße des
Wurzelelements.
-
em eignet sich für Größen, die von der lokalen
Schriftgröße abhängen sollen.
-
Eine einheitenlose
line-height passt sich an die jeweilige
Schriftgröße an.
-
Mit
ch kann die Zeilenlänge von Fließtext sinnvoll begrenzt
werden.
-
Viewport-Einheiten reagieren auf die Größe des Browserfensters.
-
calc() führt Berechnungen mit CSS-Werten durch.
-
min() wählt den kleinsten und max() den
größten der angegebenen Werte.
-
clamp() begrenzt einen flexiblen Wert durch einen Mindest-
und einen Höchstwert.
-
Container-relative Einheiten ermöglichen Typografie, die auf den
verfügbaren Platz einer Komponente reagiert.
-
overflow-wrap verhindert Überläufe durch lange Wörter und
URLs.
-
Responsive Typografie muss auch bei vergrößerter Schrift und Browserzoom
vollständig nutzbar bleiben.
Responsive Typografie verbindet gute Lesbarkeit mit flexiblen Schriftgrößen,
Zeilenlängen und Abständen. Die Texte passen sich an den verfügbaren Platz
an, ohne auf kleinen oder großen Bildschirmen unbrauchbar zu werden.