Overlapping text in jsPDF almost always comes from advancing the next block by a fixed single-line amount even though the previous paragraph wrapped to several lines. Fix it by selecting the font first, wrapping with splitTextToSize(), using a line-height that matches your design, and calculating each following y coordinate from the number of rendered lines. Also keep widths and coordinates in the document’s configured units, and use a Unicode-capable TTF font when standard fonts cannot render your characters.
Why jsPDF text overlaps
jsPDF positions text from explicit coordinates. A call such as doc.text('Next block', 15, 50) does not know that a paragraph drawn at y = 30 wrapped onto five lines unless your code tells it. If you increment y by the height of one line, the next heading or paragraph can be placed on top of the remaining lines.
There are four common causes:
- Fixed vertical increments: a paragraph is wrapped, but the next block uses the same offset used for one line.
- Uncontrolled width: the available width is not passed to the wrapping method, so text runs into a margin or adjacent content.
- Incorrect line spacing: lines in one multiline call are too close because the active
lineHeightFactoris unsuitable. - Unit or font mismatch: widths are calculated in points, millimeters, pixels, or inches inconsistently, or the selected font lacks required glyphs.
The official jsPDF API documentation documents multiline arrays, spacing, and coordinate behavior; the split_text_to_size module documentation documents width-aware wrapping.
The reliable fix: wrap, draw, and advance by line count
1. Choose the font and size before measuring
Font metrics affect wrapping. Set the font and size before calling splitTextToSize() so the returned lines correspond to what will actually be drawn.
#1 Best Overall
- 1 ream (500 sheets) of 8.5 x 11 white copier and printer paper for home or office use
- Multipurpose letter size copy paper works with laser/inkjet printers, copiers and fax machines
- Smooth 20lb weight paper for consistent ink and toner distribution; dries quickly and resists paper jams
- Bright white paper (92 GE; 104 Euro) offers great contrast for crisp printing and vivid color
- Virgin copy paper providing professional quality results; acid-free to prevent yellowing
2. Wrap to the real content width
Pass the width available between your left and right margins. splitTextToSize(text, maxWidth) returns an array of lines and uses the selected font’s width and kerning tables where available. Its width must use the same units as the jsPDF instance. The documented default for maxWidth is 0, which means you should not rely on automatic splitting without supplying a usable width.
3. Draw all lines together
doc.text() accepts an array of strings. Each line is shifted vertically according to the font spacing settings active before the call. Set lineHeightFactor explicitly when you need predictable spacing; the documented default is 1.15.
4. Compute the next block’s position
After drawing, advance by the number of lines multiplied by the line step, then add whatever gap your layout requires. Do not assume every paragraph occupies one line.
Complete JavaScript example
This runnable pattern uses millimeters, a 12-point font, a 180 mm text width, and an explicit line-height factor. The conversion in lineStep turns points into millimeters; adapt it if your design uses another unit or a different metric strategy.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsimport jsPDF from "jspdf";
const doc = new jsPDF({ unit: "mm", format: "a4" });
doc.setFont("helvetica", "normal");
doc.setFontSize(12);
const margin = 15;
const maxWidth = 180;
const lineHeightFactor = 1.3;
const paragraph =
"This paragraph may wrap across several lines. Its exact height depends on the selected font, size, and available width, so the next block must be positioned from the resulting line count rather than a fixed increment.";
const lines = doc.splitTextToSize(paragraph, maxWidth);
const firstY = 30;
doc.text(lines, margin, firstY, { lineHeightFactor });
// jsPDF font size is in points; convert the line step to millimeters.
const lineStep = (12 * lineHeightFactor) / 72 * 25.4;
const gap = 4;
const nextY = firstY + lines.length * lineStep + gap;
doc.text("Next block", margin, nextY);
doc.save("fixed-overlap.pdf");
The line-count calculation is an implementation pattern, not a guarantee that every font has identical visual metrics. Inspect the generated PDF after changing the font, size, width, alignment, units, or line-height setting. The project’s basic example demonstrates the same principle of using the number of wrapped lines when advancing a vertical offset.
Keeping multiline text readable
Use an explicit line-height factor
If lines inside one text() call collide, review the font size and lineHeightFactor. A factor larger than 1.15 creates more leading; a smaller factor compresses lines and can cause visual collisions, especially with tall glyphs or mixed scripts. Set the option on the call that draws the array:
Rank #2
- HP Papers is sourced from renewable forest resources and has achieved production with 0% deforestation in North America. Each ream is wrapped in a polyurethane coated paper wrapper to protect the cut sheets from moisture damage
- Sheet size – 8.5 x 11; Thickness – 20 pounds; Brightness – 92 bright white
- HP Copy&Print20 20 pounds printer paper is Forest Stewardship Council (FSC) certified and contributes toward satisfying credit MR1 under LEED (Leadership in Energy and Environmental Design)
- All HP Papers provide premium performance on HP equipment, as well as on all other printer and copier equipment; 100% satisfaction guaranteed; ColorLok technology provides more vivid colors, bolder blacks and faster drying
- Superior quality, reliability, and dependability for high-volume printing at home, at school and in the office; HP Copy&Print20 print and copy paper prevents yellowing over time to ensure a long-lasting appearance for added archival quality
doc.text(lines, margin, firstY, { lineHeightFactor: 1.35 });
Do not confuse line spacing with paragraph spacing
lineHeightFactor controls spacing between lines in the same multiline output. The extra gap between separate paragraphs is your own layout value, such as gap = 4. Keep those calculations separate so changing line spacing does not accidentally remove the paragraph gap.
Account for headings and labels
A heading may use a different font size from the paragraph below it. Measure and place each block with the settings that will draw it, then update the cursor after that block. A simple cursor helper prevents stale coordinates:
function drawParagraph(doc, text, x, y, width, fontSize = 12, factor = 1.3) {
doc.setFontSize(fontSize);
const lines = doc.splitTextToSize(text, width);
doc.text(lines, x, y, { lineHeightFactor: factor });
const step = (fontSize * factor) / 72 * 25.4; // for millimeters
return y + lines.length * step;
}
let y = 30;
y = drawParagraph(doc, paragraph, 15, y, 180);
y += 6;
y = drawParagraph(doc, "A second paragraph starts below the first.", 15, y, 180);
If your document unit is not millimeters, use a conversion appropriate to that unit instead of the millimeter conversion shown above.
Preventing horizontal collisions and margin overflow
Use the actual content width: page width minus left and right margins, column gutters, or any reserved space for icons. A width that is too large makes lines run into a neighboring column; a width that is too small creates unnecessary lines and increases the vertical height. Because splitTextToSize() uses font metrics where available, call it after every font change.
Coordinates passed to text() use the units selected when creating the document. The wrapping width passed to splitTextToSize() also needs to be expressed in those units. Mixing a pixel width with a millimeter document is a frequent reason for unexpected wrapping.
Unicode, missing glyphs, and apparently broken spacing
Spacing math cannot repair a missing character. jsPDF’s 14 standard PDF fonts are limited to ASCII according to the project README. For accented text, Cyrillic, Arabic, CJK, emoji, or other characters outside that coverage, integrate a TTF font containing the required glyphs and select it before measuring and drawing.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchRank #3
- 3 ream case (1,500 sheets) of 8.5 x 11 white copier and printer paper for home or office use
- Multipurpose letter size copy paper works with laser/inkjet printers, copiers and fax machines
- Smooth 20lb weight paper for consistent ink and toner distribution; dries quickly and resists paper jams
- Bright white paper (92 GE; 104 Euro) offers great contrast for crisp printing and vivid color
- Virgin copy paper providing professional quality results; acid-free to prevent yellowing
After adding a custom font, repeat the wrapping calculation. Different glyph widths can change the line count, so coordinates calculated with Helvetica may no longer be correct with the embedded font. If a character appears as a blank box or replacement glyph, verify the font file’s coverage and embedding setup before adjusting line heights.
Pagination: when the next block no longer fits
Once you calculate a block’s height, compare the next baseline with the page’s bottom margin. If it would exceed the usable page height, add a page and reset the cursor to the top margin before drawing the block. Keep the page dimensions and margins in the same units as your cursor calculations. For a structured document with tables or many flowing elements, a higher-level layout or table plugin may calculate more of the pagination, but the official material cited here does not establish a specific plugin recommendation. You still need to verify font support, widths, and the resulting PDF.
Three implementation approaches
| Approach | Width control | Vertical layout | Best use |
|---|---|---|---|
splitTextToSize() plus manual cursor |
Explicit and predictable | Your code accounts for line count, spacing, and page breaks | Custom reports and precise layouts |
text() with a maxWidth option |
Delegated to the text call | You still need to know the rendered height before placing following blocks | Short, simple text where surrounding layout is controlled |
| Higher-level layout or table plugin | Depends on the plugin | May automate rows and pagination; specific behavior is not established by the cited sources | Structured tables and document flows |
For paragraphs that determine where later content goes, explicit splitting and a cursor is the clearest approach because you can inspect the line array and calculate its height.
Debugging checklist
- Log the array returned by
splitTextToSize()and confirm its length matches the visible lines. - Log every block’s starting
x,y, width, font name, font size, and line-height factor. - Confirm that all widths and coordinates use the document’s configured unit.
- Check that the next block uses the previous block’s line count, not a hard-coded one-line increment.
- Temporarily draw a rectangle around the intended text width to expose margin and column mistakes.
- Test with a short one-line string and a deliberately long paragraph; if only the long case fails, the cursor calculation is incomplete.
- After changing fonts or sizes, recalculate lines instead of reusing an earlier array.
- Open the PDF in more than one viewer if spacing appears inconsistent; viewer rendering can make small metric differences more noticeable.
Common errors and fixes
The next paragraph starts inside the previous paragraph
Cause: the code adds a fixed amount to y. Fix: calculate the line step and multiply it by lines.length, then add a paragraph gap.
Text reaches the right margin
Cause: no usable maximum width, or a width expressed in the wrong unit. Fix: calculate the available width from page and margin values and pass it to splitTextToSize().
Lines in one array are too tight
Cause: an unsuitable line-height factor or a font with taller glyphs. Fix: set lineHeightFactor explicitly and retest with the actual font.
Rank #4
- 5 ream case (2,500 sheets) of 8.5 x 11 white copier and printer paper for home or office use
- Multipurpose letter size copy paper works with laser/inkjet printers, copiers and fax machines
- Smooth 20lb weight paper for consistent ink and toner distribution; dries quickly and resists paper jams
- Bright white paper (92 GE; 104 Euro) offers great contrast for crisp printing and vivid color
- Virgin copy paper providing professional quality results; acid-free to prevent yellowing
Wrapping changes after a font change
Cause: font metrics and kerning differ. Fix: select the final font before splitting, then recompute every dependent coordinate.
Non-English characters are missing
Cause: the 14 standard fonts do not cover the required Unicode characters. Fix: embed and select a TTF font containing those glyphs; spacing changes alone will not help.
A fix works in one jsPDF release but not another
Check the API reference matching the version installed in your project. The current documentation may describe behavior or options that differ from an older release.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your PDF workflow also needs reliable website captures, ScreenshotNeo provides a single HTTP request rather than a browser script. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before the capture. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether it was billed. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Example cURL request (see the ScreenshotNeo documentation for options):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account.
Recommended Free Tools
FAQ
Does text() automatically wrap paragraphs?
It can draw an array of lines, but you should create that array deliberately with splitTextToSize() when layout depends on the resulting height.
Best Value
- Made in USA: HP Papers is sourced from renewable forest resources and has achieved production with 0% deforestation in North America.
- Optimized for HP technology: All HP Papers provide premium performance on HP equipment, as well as on all other printer and copier equipment.
- Perfect everyday office paper: Superior quality, reliability, and dependability for high-volume printing at home, at school and in the office. Perfect for everyday black and white printing.
- Certified sustainable: HP Office20 20lb printer paper is Forest Stewardship Council (FSC) certified and contributes toward satisfying credit MR1 under LEED (Leadership in Energy and Environmental Design).
- ColorLok technology printing paper: ColorLok technology provides more vivid colors, bolder blacks and faster drying.
Why does changing only the page size alter overlap?
Page size changes the available width and possibly the number of wrapped lines. Recalculate line arrays and downstream coordinates for the new page dimensions.
Can I fix overlap by reducing the font size?
Reducing the size may hide the symptom but does not correct a stale cursor or incorrect width. Fix the wrapping and height calculation first, then choose typography that fits.
Frequently Asked Questions
Does text() automatically wrap paragraphs?
It can draw an array of lines, but you should create that array deliberately with splitTextToSize() when layout depends on the resulting height.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Why does changing only the page size alter overlap?
Page size changes the available width and possibly the number of wrapped lines. Recalculate line arrays and downstream coordinates for the new page dimensions.
Can I fix overlap by reducing the font size?
Reducing the size may hide the symptom but does not correct a stale cursor or incorrect width. Fix the wrapping and height calculation first, then choose typography that fits.
Quick Recap
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.

