PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUse jsPDF’s doc.html() method with a renderable export source. For a div hidden in your interface, either reveal it only while exporting or, preferably, let html2canvas modify a cloned document through onclone. The clone approach keeps the live page unchanged while making hidden content visible to the renderer.
Choose how the hidden content becomes renderable
A browser cannot lay out an element whose own display, visibility, dimensions, or hidden ancestor prevent rendering. jsPDF does not read a hidden div as a special PDF object; its HTML path renders the element through html2canvas and then places the result into the PDF. Your export code therefore needs a source that has usable layout at capture time.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
Building Scalable Web Sites | $18.03 | Buy on Amazon |
| Approach | Live interface changes? | Best use | Trade-off |
|---|---|---|---|
| Temporarily reveal the original | Yes, briefly | A small export with simple state | Requires careful cleanup if rendering fails |
Use html2canvas.onclone |
No | The UI must remain untouched | Ancestor styles, dimensions, and asynchronous content still need checking |
| Build a dedicated export clone | No | Reports needing their own CSS, width, and controls | More DOM and styling work |
The official html2canvas configuration documents onclone as a hook that receives the cloned document. Changes made there affect the clone used for rendering, not the original page. The exact CSS needed depends on your app, so inspect hidden ancestors and the element’s dimensions rather than assuming one style change fixes every case.
Minimal export when the div can be shown briefly
This is the shortest implementation. It records the existing inline styles, makes the target renderable, exports it, and restores the styles in a finally block so an exception does not leave the interface exposed.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
async function exportVisibleDiv() {
const element = document.getElementById('report');
if (!element) throw new Error('Missing #report');
const oldDisplay = element.style.display;
const oldVisibility = element.style.visibility;
try {
element.style.display = 'block';
element.style.visibility = 'visible';
const doc = new jsPDF();
await new Promise((resolve, reject) => {
doc.html(element, {
callback: pdf => {
pdf.save('report.pdf');
resolve();
},
x: 10,
y: 10,
autoPaging: 'text'
});
});
} finally {
element.style.display = oldDisplay;
element.style.visibility = oldVisibility;
}
}
Call exportVisibleDiv() from your button handler after jsPDF and its HTML dependencies are loaded. If the div is hidden by a parent, changing the child alone may not help. In that case, reveal the relevant ancestor as well, or use an export-only clone with explicit dimensions.
Preferred method: make the cloned document visible
With this pattern, the page the user sees never changes. The renderer clones the document, finds the target in that clone, and changes its display and visibility before capture.
function exportHiddenDiv() {
const element = document.getElementById('report');
if (!element) throw new Error('Missing #report');
const doc = new jsPDF();
doc.html(element, {
html2canvas: {
onclone(clonedDocument) {
const exportElement = clonedDocument.getElementById('report');
if (!exportElement) return;
exportElement.style.display = 'block';
exportElement.style.visibility = 'visible';
exportElement.style.position = 'static';
exportElement.style.width = '900px';
}
},
callback(pdf) {
pdf.save('report.pdf');
},
x: 10,
y: 10,
autoPaging: 'text'
});
}
Keep the selector identity stable in the clone. If the element is inside a hidden parent, make that parent renderable in onclone too. A dedicated export clone is more predictable when the screen version relies on tabs, collapsed panels, fixed positioning, or responsive widths.
Creating a dedicated export clone
Clone the report, remove interface-only controls, append it to an off-screen container with a known width, and pass that clone to doc.html(). Do not use display:none on the container, because that prevents layout.
function exportReportClone() {
const source = document.getElementById('report');
if (!source) throw new Error('Missing #report');
const wrapper = document.createElement('div');
wrapper.style.position = 'fixed';
wrapper.style.left = '-100000px';
wrapper.style.top = '0';
wrapper.style.width = '900px';
wrapper.style.background = '#fff';
const clone = source.cloneNode(true);
clone.style.display = 'block';
clone.style.visibility = 'visible';
clone.querySelectorAll('[data-html2canvas-ignore]').forEach(node => node.remove());
wrapper.appendChild(clone);
document.body.appendChild(wrapper);
const doc = new jsPDF();
doc.html(clone, {
callback(pdf) {
pdf.save('report.pdf');
wrapper.remove();
},
x: 10,
y: 10,
width: 190,
windowWidth: 900,
autoPaging: 'text'
});
}
For production code, also remove the wrapper when rendering reports an error. If your report contains data populated asynchronously, wait until that data and its fonts or images are ready before calling jsPDF.
Configure page layout, scaling, and pagination
jsPDF HTML options
callbackreceives the PDF instance; callsave()there.xandyset the starting position in the PDF.widthcontrols the rendered HTML width in the PDF coordinate system.windowWidthinfluences the layout viewport used for the HTML render. It is separate from html2canvas’s similarly named media-query setting.autoPaging: 'text'attempts to avoid cutting text and is most suitable for mostly single-column text.trueor'slice'can split text or shapes at page boundaries.- Set a filename in
save(); jsPDF’s HTML API also supports documented margin, filename, and font-face settings.
html2canvas capture options
scalecontrols raster density. A higher value can improve small text but increases memory and rendering time.width,height,x,y,scrollX, andscrollYdefine the capture region.windowWidthandwindowHeightaffect the cloned browser viewport and responsive CSS. Do not confuse this with jsPDF’s sizing option.useCORSrequests cross-origin images that permit CORS. It is not a bypass for servers that omit the required headers.- A proxy can be used for cross-origin assets when your deployment provides an appropriate proxy.
oncloneis the place to adjust visibility, add export-only styles, or remove controls without mutating the live document.data-html2canvas-ignoreexcludes an element from the render. Add it to buttons, menus, or other controls that should not appear in the PDF.onErrorcan report resources that fail to load or render.
doc.html(element, {
html2canvas: {
scale: 2,
useCORS: true,
onclone(clonedDocument) {
clonedDocument.querySelectorAll('.screen-only').forEach(node => {
node.style.display = 'none';
});
},
onError(error) {
console.error('html2canvas resource error', error);
}
},
width: 190,
windowWidth: 900,
autoPaging: 'text',
callback: pdf => pdf.save('report.pdf')
});
Make hidden reports print correctly
Give the export a real size
Responsive rules can produce a different report when the clone has an unexpected viewport. Set a stable clone width and coordinate it with jsPDF’s width and html2canvas’s viewport options. Check the rendered element’s getBoundingClientRect() in the clone workflow if the PDF is blank or only a narrow strip.
Wait for content and fonts
Charts, images, and data inserted after the click may not exist when rendering begins. Resolve the request that supplies the data first, wait for images to complete, and then export. For web fonts, wait for document.fonts.ready where supported. Missing fonts can change line wrapping and page breaks.
Exclude interface controls
Mark a print button or close icon with data-html2canvas-ignore, or remove it in the cloned document. This avoids exporting controls that only make sense on screen.
Troubleshooting blank, clipped, or incomplete PDFs
The PDF is blank
- Confirm the target ID exists and is passed to
doc.html(). - Check whether the target or an ancestor still has
display:none,visibility:hidden, zero dimensions, or a collapsed panel state. - In
onclone, make every hidden ancestor needed for layout visible and give the export a width. - Ensure asynchronous data has finished loading before starting capture.
Only some images appear
Cross-origin images require server permission through CORS, or a suitable proxy. Setting useCORS: true cannot override a server that does not send the required headers. Use onError to identify failed resources.
Text or graphics are cut at page breaks
Try autoPaging: 'text' for text-heavy, single-column content. The slice modes may divide a shape or text chunk. For complex dashboards, insert deliberate page sections in the export clone and test at the final width.
The layout is too small, too large, or wraps differently
Separate the problems: adjust the export width and jsPDF width for sizing; adjust html2canvas scale for pixel density; adjust viewport settings for responsive breakpoints. A larger scale does not correct an incorrect CSS width.
The page looks unlike the browser
HTML rendering is not identical to the browser’s print engine. CSS effects, external fonts, images, fixed elements, and page breaks may need export-specific styles. Treat the PDF as a separately tested output rather than promising a perfect visual clone.
Performance and reliability considerations
- Large, long pages consume more memory because html2canvas rasterizes content. Capture only the report area and avoid unnecessarily high
scale. - Use a fixed export width to make wrapping and pagination repeatable across devices.
- Keep the clone cleanup in both success and failure paths.
- Cache or preload assets that must appear, but verify that the final URLs permit CORS.
- Test long text, empty states, slow images, narrow mobile layouts, and reports with hidden ancestors.
- For a sensitive report, remember that client-side rendering exposes the report data to the browser; enforce your application’s normal authorization before generating it.
Or skip the browser setup
ScreenshotNeo provides a website screenshot and PDF API when the source is a URL rather than an in-page hidden DOM node. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. Every plan includes the features, with 1,000 free shots per month without a card and paid plans starting at $5 for 3,000 shots.
See the ScreenshotNeo documentation for the complete option list, including PDF paper size, margins, landscape mode, page ranges, custom CSS and JavaScript, selectors, waits, cookies, headers, device presets, geolocation, caching, signed links, asynchronous jobs, bulk capture, and usage reporting.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
If your report is available at a protected or otherwise configurable URL, ScreenshotNeo can supply custom headers, cookies, authorization, waits, and JavaScript through its documented options. Start with a free account at ScreenshotNeo (1,000 screenshots a month, no card).
Frequently Asked Questions
Can jsPDF export an element that is hidden with a closed tab or accordion?
Yes, if the export source is made renderable in the cloned document or in a dedicated export clone. Reveal required ancestors and assign a usable width before calling doc.html().
Recommended Free Tools
Does onclone change my live page?
No. The hook runs against the cloned document used by html2canvas. Changes to the clone do not alter the original DOM, although you still need to account for styles inherited from hidden ancestors.
Why are external images missing even with useCORS?
The image server must grant CORS access. The option requests CORS loading; it cannot bypass missing response headers. Use an allowed proxy or same-origin assets.
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.

