Meet het opgemaakte DOM-element bij de beoogde viewportbreedte om de grootte van een tekstvoorbeeld in de browser te bepalen. Gebruik Canvas voor metrische gegevens van tekst op één regel. Deze gids laat zien hoe je beide op een Mac vergelijkt en begrijpt waarom de breedtes en hoogtes verschillen.
De praktische taak is te bepalen hoeveel ruimte een synthetisch kaartlabel nodig heeft wanneer de viewport van de browser verandert. Een bruikbaar resultaat legt de viewport, de beschikbare tekstbreedte, de lettertype-instellingen en het gemeten kader samen vast. Een breedte zonder die omstandigheden is moeilijk te reproduceren.
Welke tekstbreedte en -hoogte moet je meten?
Browser-API's beantwoorden verschillende vragen over afmetingen. Kies voordat je iets berekent de meting die past bij de beslissing die je moet nemen.
| Je vraag | Meting | Wat deze weergeeft |
|---|---|---|
| Hoe ver schuift één string zonder afbreking horizontaal op? | Canvas measureText(text).width |
De breedte van de tekstvoortgang |
| Wat zijn de grenzen van de glyphvormen op Canvas? | Canvas-eigenschappen actualBoundingBox… |
De grenzen van glyphs ten opzichte van het uitlijningspunt en de basislijn |
| Hoeveel lay-outruimte neemt een kaart in? | Element getBoundingClientRect() |
Het omvattende kader, inclusief opvulling en randen |
| Waar bevinden de tekstfragmenten zich na het afbreken? | Range getClientRects() |
Rechthoeken die bij de geselecteerde tekst horen |
| Welke rechthoek omvat die tekstfragmenten? | Range getBoundingClientRect() |
Hun gecombineerde omvattende rechthoek |
De breedte van de Canvas-tekstvoortgang en de glyphbreedte kunnen verschillen: cursieve vormen kunnen buiten hun voortgang uitsteken. Bereken voor de glyphgrenzen de breedte als actualBoundingBoxLeft + actualBoundingBoxRight en de hoogte als actualBoundingBoxAscent + actualBoundingBoxDescent. Deze metingen gebruiken CSS-pixels. TextMetrics — MDN
Een elementmeting omvat opvulling en randen, terwijl een tekstgerichte Range de geselecteerde tekst meet met behulp van lettertypemetrieken. Geen van beide mag worden omschreven als een exacte rechthoek van gekleurde pixels. De W3C-specificatie definieert horizontale tekstrechthoeken van Range op basis van stijg- en daallengte en tekstvoortgang. Element: getBoundingClientRect() method — MDN, CSSOM View Module — W3C
Gebruik voor een voorbeeld van de browsergrootte het elementkader om ruimte toe te wijzen en de Range-rechthoeken om de tekststroom te inspecteren. Houd Canvas-metingen als afzonderlijke referentie voor de string zonder afbreking.
Stel eerst de viewport en tekstomstandigheden in
Open DevTools in Chrome op je Mac, schakel Toggle device toolbar in en kies Responsive onder Dimensions. Voer de beoogde breedte en hoogte in de viewportvelden in. Chrome documenteert zowel numerieke invoer als het slepen om de viewport aan te passen. Gebruik voor een desktopvoorbeeld het apparaattype desktop als die instelling beschikbaar is. Simulate mobile devices with device mode — Chrome for Developers
Maak onderscheid tussen viewportbreedte en tekstbreedte. Een kaart kan een maximale breedte, buitenmarges, opvulling en randen hebben. Als de kaart zijn maximale breedte bereikt, zorgt een bredere browser niet meer voor een groter tekstgebied.
Stel bijvoorbeeld dat een kaart een illustratieve breedte van 360px voor het randkader heeft, horizontale opvulling van 16px aan beide zijden en twee randen van 1px. De beschikbare inhoudsbreedte is 360 − 32 − 2 = 326px. Dat is de breedte die beschikbaar is voor tekstafbreking. De omvattende rechthoek van het element geeft nog steeds 360px aan. Dit volgt uit de gedocumenteerde meetwijze voor het randkader. Element: getBoundingClientRect() method — MDN
Stem de instellingen voor lettertypefamilie, gewicht, grootte, stijl, regelhoogte, spatiëring en afbreekregels af op het beoogde resultaat. In het bijzonder laat white-space: normal witruimte samenvallen en is afbreking toegestaan, terwijl pre-wrap witruimte en regeleinden in de broncode behoudt en afbreking toch toestaat. Een voorbeeld met de ene instelling kan de andere niet betrouwbaar weergeven. white-space — MDN
Maak ook onderscheid tussen lettergrootte en regelhoogte. Bij horizontale tekst loopt line-height mee in de bepaling van de hoogte van de regelbox; dit beschrijft niet de zichtbare hoogte van de letters. Voor een lettertype van 16px met een regelhoogte van 24px is dus een andere hoogtemeting nodig dan voor de glyphgrenzen op Canvas. line-height — MDN
Voer een volledig synthetisch tekstvoorbeeld uit
Open een leeg tabblad, open DevTools, selecteer Console en voer het volgende volledige browserscript één keer uit. Het maakt een neutrale kaart en een meetrapport. Er zijn geen bibliotheek, extern lettertype, bestaande selector of HTML-bestand nodig. Herlaad het lege tabblad voordat je nog een exemplaar uitvoert.
De kaart volgt de viewport totdat deze een breedte van 480px voor het randkader bereikt. Het rapport wordt bijgewerkt wanneer het venster of de gesimuleerde viewport van grootte verandert. Dit voorbeeld is bewust beperkt tot een gewoon horizontaal tekstblok met uniforme opmaak. De browserafhankelijke code is geïnspecteerd, maar tijdens de voorbereiding niet in een browser uitgevoerd.
(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));
De aanroepen van Element en Range gebruiken de werkelijke browserlay-out. Canvas meet dezelfde synthetische string als één onafgebroken tekstregel. De HTML-standaard voor Canvas vervangt ASCII-witruimte door spaties; een regeleinde doorgeven aan measureText() maakt geen CSS-alinea met meerdere regels. HTML Standard: The canvas element — WHATWG
Het script wacht op document.fonts.ready nadat de lay-out is ingesteld. MDN vermeldt dat deze promise wordt vervuld zodra de laad- en lay-outbewerkingen voor gebruikte lettertypen zijn voltooid. Dat betekent niet dat elk opgegeven lettertype is geladen of dat het oorspronkelijk gewenste lettertype daadwerkelijk wordt weergegeven. Document: fonts property — MDN
Lees de resultaten en bepaal of de tekst past
Begin met Available text width en vergelijk vervolgens de kaarthoogte bij twee viewportgroottes. Als tekstafbreking een regel toevoegt, verandert de kaarthoogte terwijl de voortgang van de tekst zonder afbreking op Canvas gelijk kan blijven. Die combinatie helpt onderscheid te maken tussen een verandering in tekstafbreking en een verandering van lettertype.
Voor dit voorbeeld zijn de volgende breedtes illustratieve berekeningen, geen gemeten resultaten voor een lettertype. Ze gaan ervan uit dat de lay-outviewport de aangegeven breedte heeft en dat de stijlen van het script ongewijzigd blijven.
| Breedte van lay-outviewport | Breedte van kaartkader | Beschikbare tekstbreedte |
|---|---|---|
360px |
312px |
278px |
800px |
480px |
446px |
1200px |
480px |
446px |
De laatste twee rijen laten zien waarom tekst bij een bredere browser soms op dezelfde plek wordt afgebroken: de kaart heeft zijn maximale breedte al bereikt. Alleen de viewport veranderen kan de kaart geen extra inhoudsruimte geven.
Voor een eenvoudig blok met uitsluitend uniforme tekst neemt een illustratieve lay-out van drie regels bij een regelhoogte van 24px 72px aan regelboxruimte in. Tel daar 32px verticale opvulling en 2px aan randen bij op voor een illustratieve kaarthoogte van 106px. Deze berekening helpt het resultaat te begrijpen; bij complexere inhoud of opmaak is de gemeten DOM-hoogte doorslaggevend. line-height — MDN
Beschouw Range fragment count niet automatisch als een universeel aantal regels. De Range-API geeft volgens de selectieregels rechthoeken voor tekst en elementen terug. Rijke tekst, geneste elementen en gefragmenteerde lay-out kunnen een ingewikkeldere reeks rechthoeken opleveren. Het voorbeeld selecteert slechts één gewone tekstnode om de diagnose begrijpelijk te houden. CSSOM View Module — W3C
Vermijd ook het schatten van de afgebroken hoogte met ceil(unwrappedWidth / availableWidth). Die formule gaat ervan uit dat tekst op willekeurige horizontale posities kan worden afgebroken. Tekstafbreking in de browser moet de ingestelde witruimte- en afbreekregels volgen, dus meet in plaats daarvan het afgebroken blok. white-space — MDN
Wat controleer je als metingen niet overeenkomen?
Controleer eerst de meetgrens. Een rechthoek van een kaart over de volledige breedte en een smallere Range-rechthoek kunnen allebei kloppen. De kaart reserveert lay-outruimte; de Range beschrijft de geselecteerde tekst. De glyphhoogte op Canvas levert een derde waarde met een ander doel.
Controleer vervolgens of de lettertypen klaar zijn. Als je een webfont toevoegt, kan document.fonts.load(fontSpecification, sampleText) expliciet de overeenkomstige lettertypevarianten opvragen voordat je meet. Handel afwijzingen af in plaats van stilzwijgend een geslaagd resultaat te gebruiken als vervanging. Het optionele tekstargument filtert op Unicode-bereiken; het controleert niet of afzonderlijke glyphs beschikbaar zijn. FontFaceSet: load() method — MDN
Behoud de grenzen van tekstvormgeving wanneer je de breedte van een label berekent. Meet de volledige string in plaats van afzonderlijk gemeten tekenbreedtes bij elkaar op te tellen. De Canvas-specificatie bereidt een gepositioneerde glyphreeks voor met het huidige lettertype en de huidige tekstinstellingen; het resultaat is de juiste meeteenheid voor die string. Beperk de Canvas-vergelijking in dit voorbeeld tot de vermelde lettertype-instellingen en ga er niet van uit dat die elke typografische CSS-functie nabootst. HTML Standard: The canvas element — WHATWG
Meet bij een bestaande pagina het daadwerkelijke onderdeel op zijn huidige plek. Tekst verplaatsen naar een generiek verborgen kader verandert de lay-outomstandigheden, tenzij je ook de relevante stijlen en de omringende context reproduceert. Elementen zonder bijbehorende lay-outbox kunnen geen bruikbare normale kadermetingen leveren, en CSS-transformaties beïnvloeden de rechthoeken die deze API's rapporteren. Het synthetische voorbeeld vermijdt beide complicaties. CSSOM View Module — W3C
Hoe herhaal je het voorbeeld bij verschillende browsergroottes?
Voer voor incidentele controles elke viewportgrootte handmatig in en noteer het rapport. Vergelijk breedtes rond het punt waarop de tekstafbreking verandert, in plaats van alleen een zeer smalle en een zeer brede lay-out te controleren.
Voor herhaalde controles ondersteunt Playwright expliciete viewportafmetingen en een afzonderlijke instelling deviceScaleFactor. De documentatie staat ook toe de viewport van een apparaatpreset te overschrijven. Dit biedt een ondersteunde manier om dit te automatiseren: stel de viewport in, laad de pagina, wacht tot de lettertypen en relevante inhoud zijn geladen en verzamel vervolgens de DOM-metingen in de browser. Emulation — Playwright
Houd CSS-afmetingen gescheiden van de pixeldichtheid van het scherm. Playwright biedt viewport en schaalfactor als afzonderlijke instellingen; Canvas-tekstmetingen worden uitgedrukt in CSS-pixels. Een scherm met hogere dichtheid vereist op zichzelf niet dat je de CSS-breedte voor een label verdubbelt. Emulation — Playwright, TextMetrics — MDN
Een bruikbaar resultaat van het voorbeeld is dus een kort overzicht van de omstandigheden: browser, viewport, tekst, typografie, inhoudsbreedte en gemeten kaarthoogte. Gebruik het DOM-resultaat om de grootte van het afgebroken onderdeel te bepalen, bewaar Canvas-metingen voor vragen over één tekstregel en herhaal de meting in elke browser die je wilt weergeven.
Bronnen
- CSSOM View Module — W3C.
- HTML Standard: The canvas element — WHATWG.
- TextMetrics — MDN Web Docs.
- Element: getBoundingClientRect() method — MDN Web Docs.
- Document: fonts property — MDN Web Docs.
- FontFaceSet: load() method — MDN Web Docs.
- white-space — MDN Web Docs.
- line-height — MDN Web Docs.
- Simulate mobile devices with device mode — Chrome for Developers.
- Emulation — Playwright.