Um eine Browser-Textvorschau zu dimensionieren, messen Sie das angeordnete DOM-Element bei der vorgesehenen Viewport-Breite. Verwenden Sie Canvas für einzeilige Textmetriken. Diese Anleitung zeigt, wie Sie beides auf einem Mac vergleichen und verstehen, warum sich Breiten und Höhen unterscheiden.
Die praktische Aufgabe besteht darin, herauszufinden, wie viel Platz die Beschriftung einer synthetischen Karte benötigt, wenn sich der Browser-Viewport ändert. Ein nützliches Ergebnis hält Viewport, verfügbare Textbreite, Schrifteinstellungen und gemessene Box gemeinsam fest. Eine Breite ohne diese Bedingungen lässt sich nur schwer reproduzieren.
Welche Textbreite und -höhe sollten Sie messen?
Browser-APIs beantworten verschiedene Fragen zur Größe. Wählen Sie vor jeder Berechnung die Messung, die zu Ihrer Entscheidung passt.
| Ihre Frage | Messung | Was sie darstellt |
|---|---|---|
| Wie weit reicht eine einzelne, nicht umgebrochene Zeichenfolge horizontal? | Canvas measureText(text).width |
Textvorschubbreite |
| Welche Grenzen haben die Glyphenformen auf dem Canvas? | Canvas-Eigenschaften actualBoundingBox… |
Glyphengrenzen relativ zum Ausrichtungspunkt und zur Grundlinie |
| Wie viel Layoutfläche nimmt eine Karte ein? | Element getBoundingClientRect() |
Sein Begrenzungsrahmen einschließlich Innenabständen und Rahmen |
| Wo liegen die Textfragmente nach dem Umbruch? | Range getClientRects() |
Rechtecke, die dem ausgewählten Text zugeordnet sind |
| Welches Rechteck umfasst diese Textfragmente? | Range getBoundingClientRect() |
Ihr gemeinsames Begrenzungsrechteck |
Canvas-Vorschubbreite und Glyphenbreite können sich unterscheiden: Kursivformen können über ihren Vorschub hinausreichen. Für die Glyphengrenzen berechnen Sie die Breite als actualBoundingBoxLeft + actualBoundingBoxRight und die Höhe als actualBoundingBoxAscent + actualBoundingBoxDescent. Diese Messungen verwenden CSS-Pixel. TextMetrics — MDN
Eine Elementmessung umfasst Innenabstände und Rahmen, während ein reiner Text-Range den ausgewählten Text anhand von Schriftmetriken misst. Keine der beiden Messungen sollte als exaktes Rechteck der gezeichneten Pixel beschrieben werden. Die W3C-Spezifikation definiert horizontale Range-Textrechtecke anhand von Oberlänge, Unterlänge und Textvorschub. Element: Methode getBoundingClientRect() — MDN, CSSOM View Module — W3C
Verwenden Sie für eine Größen Vorschau im Browser die Element-Box, um Platz zuzuweisen, und die Range-Rechtecke, um den Textfluss zu untersuchen. Behalten Sie Canvas-Messungen als separate Referenz für die nicht umgebrochene Zeichenfolge bei.
Legen Sie zuerst Viewport und Textbedingungen fest
Öffnen Sie in Chrome auf Ihrem Mac die DevTools, aktivieren Sie Gerätesymbolleiste umschalten und wählen Sie unter Abmessungen die Option Responsiv. Geben Sie die vorgesehene Breite und Höhe in die Viewport-Felder ein. Chrome dokumentiert sowohl die numerische Eingabe als auch die Größenänderung durch Ziehen. Verwenden Sie für eine Desktop-Vorschau den Gerätetyp „Desktop“, sofern diese Steuerung verfügbar ist. Mobilgeräte mit dem Gerätemodus simulieren — Chrome für Entwickler
Unterscheiden Sie zwischen Viewport-Breite und Textbreite. Eine Karte kann eine maximale Breite, Außenabstände, Innenabstände und Rahmen haben. Wenn Sie die Browser-Breite vergrößern, wächst der Textbereich nicht weiter, sobald die Karte ihre maximale Breite erreicht hat.
Angenommen, eine Karte hat eine beispielhafte Rahmenbox-Breite von 360px, horizontale Innenabstände von jeweils 16px und zwei Rahmen von je 1px. Ihre verfügbare Inhaltsbreite beträgt 360 − 32 − 2 = 326px. Das ist die für den Textumbruch verfügbare Breite. Das Begrenzungsrechteck des Elements weist weiterhin 360px aus. Dies entspricht dem dokumentierten Verhalten der Messung der Rahmenbox. Element: Methode getBoundingClientRect() — MDN
Passen Sie Schriftfamilie, Schriftschnitt, Größe, Stil, Zeilenhöhe, Abstände und Umbruchregeln an die vorgesehenen Bedingungen an. Insbesondere fasst white-space: normal Leerraum zusammen und erlaubt Umbrüche, während pre-wrap Leerraum und Zeilenumbrüche im Quelltext erhält und dennoch Umbrüche zulässt. Eine Vorschau mit der einen Einstellung kann die andere nicht zuverlässig abbilden. white-space — MDN
Unterscheiden Sie außerdem zwischen Schriftgröße und Zeilenhöhe. Bei horizontaler Schreibrichtung wirkt sich line-height auf die Höhe der Zeilenbox aus; sie beschreibt nicht die sichtbare Höhe der Buchstaben. Eine Schriftgröße von 16px bei einer Zeilenhöhe von 24px erfordert daher eine andere Höhenberechnung als ihre Canvas-Glyphengrenzen. line-height — MDN
Führen Sie eine vollständige Vorschau mit synthetischem Text aus
Öffnen Sie einen leeren Tab, öffnen Sie die DevTools, wählen Sie Konsole aus und führen Sie das folgende vollständige Browserskript einmal aus. Es erstellt eine neutrale Karte und einen Messbericht. Dafür ist weder eine Bibliothek noch eine externe Schriftart, ein vorhandener Selektor oder eine HTML-Datei erforderlich. Laden Sie den leeren Tab neu, bevor Sie eine weitere Kopie ausführen.
Die Karte passt sich dem Viewport an, bis sie eine Rahmenbox-Breite von 480px erreicht. Der Bericht wird aktualisiert, wenn die Fenstergröße oder der emulierte Viewport geändert wird. Dieses Beispiel ist bewusst auf einen einfachen horizontalen Textblock mit einheitlicher Formatierung beschränkt. Der browserabhängige Code wurde geprüft, aber während der Vorbereitung nicht in einem Browser ausgeführt.
(async () => {
const text =
"Sample collection: round forms, soft gradients, and simple patterns.";
document.body.style.margin = "0";
const card = document.createElement("div");
card.textContent = text;
card.lang = "en";
card.dir = "ltr";
card.style.cssText = [
"box-sizing: border-box",
"width: min(480px, calc(100% - 48px))",
"margin: 24px",
"padding: 16px",
"border: 1px solid #777",
"font: normal 400 16px/24px Arial, sans-serif",
"font-kerning: normal",
"letter-spacing: 0px",
"word-spacing: 0px",
"white-space: normal",
"overflow-wrap: normal",
"word-break: normal",
"hyphens: none",
"color: #222",
"background: #f4f4f4"
].join(";");
const report = document.createElement("pre");
report.style.cssText =
"margin: 24px; white-space: pre-wrap; overflow-wrap: anywhere;";
document.body.append(card, report);
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
if (!ctx) {
report.textContent = "A Canvas 2D context is unavailable.";
return;
}
// Establish layout before waiting for the fonts used by that layout.
card.getBoundingClientRect();
await document.fonts.ready;
const format = value =>
Number.isFinite(value) ? value.toFixed(2) : "unavailable";
function measure() {
const style = getComputedStyle(card);
const box = card.getBoundingClientRect();
const horizontalExtras =
parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) +
parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);
const range = document.createRange();
range.selectNodeContents(card);
const textBox = range.getBoundingClientRect();
const fragments = Array.from(range.getClientRects());
ctx.font = "normal 400 16px Arial, sans-serif";
ctx.fontKerning = "normal";
ctx.direction = "ltr";
ctx.textAlign = "left";
ctx.textBaseline = "alphabetic";
const metrics = ctx.measureText(text);
const inkWidth =
metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
const inkHeight =
metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
report.textContent = [
"All dimensions below are CSS pixels.",
`Layout viewport: ${document.documentElement.clientWidth} x ${document.documentElement.clientHeight}`,
`Card border box: ${format(box.width)} x ${format(box.height)}`,
`Available text width: ${format(box.width - horizontalExtras)}`,
`Range bounds: ${format(textBox.width)} x ${format(textBox.height)}`,
`Range fragment count: ${fragments.length}`,
`Canvas unwrapped advance: ${format(metrics.width)}`,
`Canvas glyph bounds: ${format(inkWidth)} x ${format(inkHeight)}`,
`Computed line height: ${style.lineHeight}`
].join("\n");
}
measure();
window.addEventListener("resize", measure);
})().catch(error => console.error("Preview failed:", error));
Die Element- und Range-Aufrufe verwenden das tatsächliche Layout des Browsers. Canvas misst dieselbe synthetische Zeichenfolge als einen nicht umgebrochenen Lauf. Der HTML-Standard ersetzt bei der Canvas-Textvorbereitung ASCII-Leerraum durch Leerzeichen; die Übergabe eines Zeilenumbruchs an measureText() erzeugt keinen CSS-Absatz mit mehreren Zeilen. HTML-Standard: Das canvas-Element — WHATWG
Das Skript wartet nach dem Erstellen des Layouts auf document.fonts.ready. Laut MDN wird dieses Promise erfüllt, sobald das Laden und die Layoutvorgänge für verwendete Schriftarten abgeschlossen sind. Das bedeutet nicht, dass alle deklarierten Schriftarten geladen wurden oder dass die ursprünglich bevorzugte Schrift tatsächlich angezeigt wird. Document: Eigenschaft fonts — MDN
Lesen Sie die Ergebnisse und entscheiden Sie, ob der Text passt
Beginnen Sie mit Verfügbare Textbreite und vergleichen Sie dann die Kartenhöhe bei zwei Viewport-Größen. Wenn durch den Umbruch eine Zeile hinzukommt, ändert sich die Kartenhöhe, während der nicht umgebrochene Canvas-Vorschub unverändert bleiben kann. Diese Kombination hilft dabei, eine Änderung des Umbruchs von einer Änderung der Schriftart zu unterscheiden.
Für dieses Beispiel sind die folgenden Breiten beispielhafte Berechnungen und keine gemessenen Schriftart-Ergebnisse. Sie setzen voraus, dass der Layout-Viewport die angegebene Breite hat und die Stile des Skripts unverändert bleiben.
| Breite des Layout-Viewports | Rahmenbox-Breite der Karte | Verfügbare Textbreite |
|---|---|---|
360px |
312px |
278px |
800px |
480px |
446px |
1200px |
480px |
446px |
Die letzten beiden Zeilen erklären, warum eine breitere Browser-Ansicht den Textumbruch unverändert lassen kann: Die Karte hat ihre maximale Breite bereits erreicht. Allein durch eine Änderung des Viewports erhält die Karte nicht mehr Platz für Inhalte.
Ein einfacher Block, der nur einheitlich formatierten Text enthält, nimmt bei einem beispielhaften Layout mit drei Zeilen und einer Zeilenhöhe von 24px insgesamt 72px Zeilenbox-Fläche ein. Addiert man 32px vertikale Innenabstände und 2px für die Rahmen, ergibt sich eine beispielhafte Kartenhöhe von 106px. Diese Rechnung hilft, das Ergebnis zu verstehen; bei komplexeren Inhalten oder Formatierungen ist die gemessene DOM-Höhe jedoch maßgeblich. line-height — MDN
Behandeln Sie Range-Fragmentanzahl nicht automatisch als universelle Zeilenzahl. Die Range-API liefert Text- und Elementrechtecke gemäß ihren Auswahlregeln. Formatierter Text, verschachtelte Elemente und fragmentiertes Layout können eine komplexere Menge von Rechtecken ergeben. Im Beispiel wird nur ein einzelner einfacher Textknoten ausgewählt, damit die Diagnose verständlich bleibt. CSSOM View Module — W3C
Vermeiden Sie außerdem, die umbrochene Höhe mit ceil(unwrappedWidth / availableWidth) zu schätzen. Diese Formel setzt voraus, dass der Text an beliebigen horizontalen Positionen umgebrochen werden kann. Der Browserumbruch muss dem konfigurierten Leerraum- und Umbruchverhalten folgen. Messen Sie daher den umbrochenen Block. white-space — MDN
Was sollten Sie prüfen, wenn die Messwerte voneinander abweichen?
Prüfen Sie zuerst die Messgrenze. Ein Rechteck, das die gesamte Breite der Karte umfasst, und ein schmaleres Range-Rechteck können beide korrekt sein. Die Karte reserviert Layoutfläche; der Range beschreibt den ausgewählten Text. Die Canvas-Glyphenhöhe liefert einen dritten Wert für einen anderen Zweck.
Prüfen Sie als Nächstes, ob die Schrift bereit ist. Wenn Sie eine deklarierte Webschrift verwenden, kann document.fonts.load(fontSpecification, sampleText) vor der Messung ausdrücklich die passenden Schriftarten anfordern. Behandeln Sie eine Zurückweisung, statt stillschweigend ein erfolgreiches Ergebnis einzusetzen. Das optionale Textargument filtert nach Unicode-Bereichen; es überprüft nicht die Abdeckung einzelner Glyphen. FontFaceSet: Methode load() — MDN
Bewahren Sie beim Berechnen der Breite einer Beschriftung die Grenzen der Schriftformung. Messen Sie die vollständige Zeichenfolge, anstatt die einzeln gemessenen Zeichenbreiten zu addieren. Die Canvas-Spezifikation bereitet anhand der aktuellen Schrift- und Texteinstellungen einen positionierten Glyphenlauf vor; sein Ergebnis ist die passende Maßeinheit für diese Zeichenfolge. Beschränken Sie den Canvas-Vergleich in diesem Beispiel auf die angegebenen Schrifteinstellungen, statt davon auszugehen, dass er jedes Typografiemerkmal von CSS abbildet. HTML-Standard: Das canvas-Element — WHATWG
Messen Sie bei einer bestehenden Seite die tatsächliche Komponente an ihrem Platz. Wenn Sie Text in eine allgemeine verborgene Box verschieben, ändern sich die Layoutbedingungen, sofern Sie nicht auch die relevanten Stile und den umgebenden Kontext nachbilden. Elemente ohne zugehörige Layoutboxen liefern keine brauchbaren normalen Boxmessungen, und CSS-Transformationen beeinflussen die von diesen APIs gemeldeten Rechtecke. Das synthetische Beispiel vermeidet beide Komplikationen. CSSOM View Module — W3C
Wie können Sie die Vorschau bei mehreren Browser-Größen wiederholen?
Für gelegentliche Prüfungen geben Sie jede Viewport-Größe manuell ein und protokollieren den Bericht. Vergleichen Sie Breiten in der Nähe des Punkts, an dem sich der Umbruch ändert, statt nur ein sehr schmales und ein sehr breites Layout zu prüfen.
Für wiederholte Prüfungen unterstützt Playwright explizite Viewport-Abmessungen und eine separate Einstellung deviceScaleFactor. Die Dokumentation erlaubt außerdem, den Viewport einer Gerätevoreinstellung zu überschreiben. Das bietet einen unterstützten Automatisierungsweg: Legen Sie den Viewport fest, laden Sie die Seite, warten Sie auf die Schriftarten und relevanten Inhalte und erfassen Sie anschließend die DOM-Messwerte im Browser. Emulation — Playwright
Halten Sie CSS-Abmessungen und Pixeldichte des Displays getrennt. Playwright stellt Viewport und Skalierungsfaktor als separate Einstellungen bereit, während Canvas-Textmetriken in CSS-Pixeln angegeben werden. Ein Display mit höherer Pixeldichte erfordert für sich genommen keine Verdoppelung der CSS-Breite, die einer Beschriftung zugewiesen wird. Emulation — Playwright, TextMetrics — MDN
Ein nützliches Vorschauergebnis ist daher eine kurze Aufzeichnung der Bedingungen: Browser, Viewport, Text, Typografie, Inhaltsbreite und gemessene Kartenhöhe. Verwenden Sie das DOM-Ergebnis, um die umbrochene Komponente zu dimensionieren, behalten Sie Canvas-Metriken für Fragen zu einem einzelnen Textlauf bei und wiederholen Sie die Messung in jedem Browser, dessen Darstellung Sie abbilden müssen.
Quellen
- CSSOM View Module — W3C.
- HTML-Standard: Das canvas-Element — WHATWG.
- TextMetrics — MDN Web Docs.
- Element: Methode getBoundingClientRect() — MDN Web Docs.
- Document: Eigenschaft fonts — MDN Web Docs.
- FontFaceSet: Methode load() — MDN Web Docs.
- white-space — MDN Web Docs.
- line-height — MDN Web Docs.
- Mobilgeräte mit dem Gerätemodus simulieren — Chrome für Entwickler.
- Emulation — Playwright.