Recommended Free Tools
CanvasRenderingContext2D.fillText() draws a line of text; it does not automatically wrap a long title onto another line. To keep an OG image title inside a 1200px canvas, measure candidate lines with measureText(), break them in your code, and call fillText() once per line within an inset safe area.
Why Canvas text does not wrap
fillText(text, x, y) draws text at the specified coordinates. Without a width constraint, a long title can extend beyond the image edge. Passing the optional maxWidth argument does not add line breaks: the browser may instead condense the text horizontally or use a smaller font to fit it on one line. That can avoid overflow while making a prominent title look squeezed or unexpectedly small. See MDN’s fillText() documentation.
As an Amazon Associate I earn from qualifying purchases.
Wrap the title with measureText()
Canvas does not provide paragraph-style automatic line layout through fillText(). Your code must decide where each line ends. Set the font before measuring, test each word as part of the current line, and start a new line when the candidate would exceed your text area.
function wrapCanvasText(ctx, text, maxWidth) {
const words = text.trim().split(/s+/);
const lines = [];
let line = "";
for (const word of words) {
const candidate = line ? `${line} ${word}` : word;
if (line && ctx.measureText(candidate).width > maxWidth) {
lines.push(line);
line = word;
} else {
line = candidate;
}
}
if (line) lines.push(line);
return lines;
}
// Set the actual font before measuring or drawing.
ctx.font = "700 64px Inter, sans-serif";
ctx.textAlign = "left";
ctx.textBaseline = "top";
const padding = 72;
const maxWidth = canvas.width - padding * 2;
const lines = wrapCanvasText(ctx, title, maxWidth);
const lineHeight = 76;
lines.forEach((line, i) => {
ctx.fillText(line, padding, padding + i * lineHeight);
});
The 72px padding and 76px line height are illustrative design choices, not Canvas requirements. Choose spacing and a safe width that suit the font, image layout, and other elements. The example wraps on whitespace; a single word wider than the safe area remains too wide, so you must decide whether to split it, reduce the font size, or handle it another way.
#1 Best Overall
Keep measurement and drawing consistent
measureText() returns a TextMetrics object for the current text style, including a width in pixels. Set ctx.font before measuring, and use the same font settings when drawing. If the design uses a downloaded font, wait until it has loaded before measuring and rendering; otherwise the measured fallback font may not match the final title. MDN explains text measurement and baselines in its Canvas text-drawing tutorial.
Each separate fillText() call needs its own y-coordinate. With textBaseline = "top", the y-coordinate anchors the top of the text; other baseline settings anchor it differently. Set the baseline intentionally, then advance each line by a chosen line height that prevents overlap and fits the image height.
Rank #2
Use a safe area, not the full 1200px width
A 1200px-wide bitmap does not give the title 1200px of usable line width. Subtract left and right padding, plus any space reserved for logos or design elements. For example, 72px of padding on both sides yields a 1056px text area on a 1200px canvas. This is a layout choice, not a browser or OG-image rule.
Free tools Windows power users keep installed
One-click scans. No signup required.
Measured width is also not a guaranteed visual clipping boundary. The WHATWG HTML Standard notes that glyphs drawn with fillText() or strokeText() can spill beyond the box implied by font size and the width returned by measureText(). Leave extra room for glyph overhang, shadows, strokes, and alignment rather than placing text exactly on the calculated boundary.
Choose wrapping or maxWidth based on the design
| Approach | What it does | Trade-off |
|---|---|---|
Manual wrapping with measureText() |
Creates separate lines at breaks chosen by your code. | Preserves control over font size, line breaks, and spacing, but needs handling for oversized words and language-specific line-breaking rules. |
Single-line fillText() with maxWidth |
Fits one rendered line to a specified maximum width. | Less wrapping code, but may horizontally condense or shrink the text; it does not create multiple lines. |
For a prominent OG title that should retain a deliberate font size, use measured multiline wrapping. Use maxWidth when the title must stay on one line and you have checked that the resulting fit still looks readable.
Quick Recap
Best Value
Rank #4
Debug titles that still overflow
- Check
canvas.widthandcanvas.height, not only the canvas’s CSS display size. CSS scaling changes how the bitmap is displayed, not the drawing surface’s intrinsic dimensions. - Confirm that the intended font is loaded and that
ctx.fontis set before both measuring and drawing. - Inspect
ctx.textAlign. With left alignment, the x-coordinate marks the line’s left edge; centered and right-aligned text use different alignment points, so their coordinates need corresponding margins. - Check the baseline and line-height calculations to ensure each line starts where intended and the full title fits vertically.
- Preview wide glyphs, punctuation, emoji, and the languages your generator supports. A whitespace-based wrapper is not a complete line-breaking solution for every writing system or shaping requirement.
- If relying on
maxWidthfor one-line fitting, inspect the rendered result for compression or an unexpectedly small appearance.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




