Sales teams, HR departments, and employee onboarding flows all share a common need: batch-producing business cards. Dozens or even hundreds of names, job titles, and phone numbers must be laid out in one consistent format and exported as print-ready PDFs. The traditional path means hand-layout in design software or server-side generation, both slow and error-prone, and every personnel change restarts the whole process. dompdf.js offers a pure frontend route: write the card layout as an HTML template, loop over the personnel data, call addPage once per card, and save everything as a single multi-page PDF with unified styling, selectable text, and correct Chinese characters — no backend involvement at any step. Because the entire pipeline runs in the user's browser, the solution also scales with zero infrastructure: the same HTML template and data loop that handles ten cards handles ten thousand, with only the generation time changing. For teams that already keep personnel data in spreadsheets or HR APIs, a short mapping step converts that data into the array the template expects, so the batch workflow plugs into existing processes rather than replacing them. And because the output is a true vector PDF, the same file that goes to the printer can be emailed to the employee, attached to an offer letter, or uploaded to an intranet directory without any re-export.
In corporate HR systems, new employees need business cards printed as part of onboarding, and sales teams with frequent turnover generate card requests almost every month. Laying out cards one by one in design tools is extremely inefficient and invites inconsistent fonts and misaligned elements; batch templating is the only practical approach at scale. A batch template also removes the human factor: once the layout is approved, every card in the run is guaranteed to match, because the same styles and the same code produce every page.
Before trade shows and industry conferences, teams often need a fresh batch of cards on very short notice, leaving almost no time for backend rendering. Pure frontend generation means the moment the data is entered, the PDF is ready to download — no server queue, no template maintenance, and last-minute corrections are still possible. The speed advantage compounds as the batch grows — generating two hundred cards takes only marginally longer than generating twenty, whereas hand-layout time grows linearly with headcount.
Beyond physical printing, electronic business cards are increasingly common: HR sends candidates a card PDF with a QR code, and sales reps share e-cards with clients over chat apps. These use cases all demand fast generation, consistent formatting, and repeatable batch execution — exactly what dompdf.js provides. Beyond the obvious efficiency gain, batch export removes the coordination bottleneck that appears whenever a new hire starts or a promotion changes a title, because the update is a data change rather than a design task.
Design teams often worry that template generation means losing design freedom. In practice the opposite is true: the HTML/CSS template is a single source of truth, so a logo refresh or a new brand color is applied to the entire batch with one edit instead of re-touching every card.
Batch export also makes regional or departmental variants practical. The same template can render different languages, different contact formats, or different legal disclaimers by switching data or a couple of CSS classes, which is nearly impossible to manage by hand.
For distributed teams, the frontend approach removes coordination cost entirely: a colleague in another office enters their own data and exports their own batch, with no dependency on a central design or backend team, which matters when offices span time zones.
Business cards demand precise layout: the standard 90×54mm size, centered names and titles, and clearly separated contact lines. dompdf.js renders the DOM directly, so whatever the HTML template specifies is exactly what appears in the PDF. Layout control is far better than coordinate-based drawing libraries that require manual calculation for every element. Because rendering happens against a real CSS layout engine, relative units like mm, pt, and em behave exactly as they do in the browser, so designers can prototype a card in a normal HTML editor and trust the PDF to match.
Business cards are a heavily Chinese-language use case. dompdf.js ships with the Source Han Sans SC font built in, so properly formed Chinese text is rendered without any font configuration — names, titles, and company names never show mojibake or missing-glyph boxes. The vector output also keeps file sizes small: a two-hundred-card PDF is typically only a few hundred kilobytes, because every card shares the same font and shape definitions instead of storing repeated pixel data.
Output is a vector PDF with selectable, searchable text that stays crisp at any zoom level. One file serves both print and digital distribution, and the Rust+WASM core keeps batch generation of large documents smooth even on modest hardware. Rendering the DOM directly also means the template is inspectable: whatever CSS a developer can write and debug in the browser is exactly the CSS the PDF honors, which removes a whole class of guesswork.
Another practical advantage is debuggability. When a card looks wrong, the developer inspects the HTML template with familiar browser tools rather than reverse-engineering drawing coordinates, which shortens the fix cycle from hours to minutes.
Consistency across batches is a further benefit: because the template and fonts are fixed, the card produced for a new hire in December is visually identical to the one produced in January, which keeps brand presentation uniform over time.
For teams that must comply with print specifications, the mm-based layout maps directly onto the printer's requirements, so what is designed is what gets printed — the template effectively becomes the final artwork source.
The core idea is to write the card template as a function that takes personnel data and returns an HTML string, then loop through the data calling addPage once per person. Each card becomes an independent page, so layouts never interfere with each other and content never bleeds between pages. Wrapping the template in a function also makes testing straightforward: call the function with sample data, render the result, and verify the layout before it ever touches a real name.
If you want multiple cards on a single page (for example a three-by-three grid), write the cards as block-level elements inside one page container and let auto pagination slice the content by A4 size. Aligning the container width to 794px — the pixel width of A4 at 96 DPI — gives the most stable result. Because addPage hands control back immediately and generation proceeds in the background, you can chain the loop, show a progress indicator, and still keep the interface interactive.
The save method triggers a browser download directly, so there is no need to handle Blobs manually. If you want to preview before exporting, render the template on the page first, confirm the layout, and only then run the generation logic. The separation between data and markup means the same loop can also filter or sort the staff array before rendering, so priority groups or alphabetical order are free features.
If cards must be produced for people whose details are incomplete — a missing phone number or a yet-to-be-assigned title — decide on a placeholder convention up front, such as an em dash or the text 'TBD', so the template never renders broken layout.
When the batch is large, consider generating a preview PDF of the first few cards before committing to the full run. A quick visual check of two or three pages catches template errors early and saves the time of regenerating hundreds of pages.
For teams that want a file named per person or per department, the save method accepts a computed filename, so a single loop can produce individual PDFs per employee or one combined file, depending on the business rule.
import { DomPDF } from 'dompdf.js';
const staff = [
{ name: 'Zhang Wei', title: 'Sales Director', phone: '138-0000-0001', email: 'zhangwei@example.com' },
{ name: 'Li Na', title: 'Product Manager', phone: '138-0000-0002', email: 'lina@example.com' },
];
const cardHTML = (p) => `
<div style="width:90mm;height:54mm;border:1px solid #ccc;padding:6mm">
<div style="font-size:14pt;font-weight:bold">${p.name}</div>
<div style="font-size:10pt;color:#666">${p.title}</div>
<hr style="margin:3mm 0">
<div style="font-size:9pt">Tel: ${p.phone}</div>
<div style="font-size:9pt">Email: ${p.email}</div>
</div>`;
const pdf = new DomPDF();
staff.forEach((p) => pdf.addPage(cardHTML(p), { format: 'A4', margin: '10mm' }));
pdf.save('business-cards.pdf');
The standard business card size is 90×54mm, so it is best to design the template directly in mm units to avoid pixel conversion errors. Leave a safe margin around the edges, and add bleed as required by the print shop when the cards are going to a commercial printer. A good rule of thumb is to keep the total content footprint within roughly 80mm by 46mm so that even slightly off-center cutting at the print shop never clips text.
For the visual hierarchy, separate company name, person's name, job title, and contact details into clear levels: the name in large bold type, the title in a secondary size, and contact information in a consistent small size. This makes the card easy to scan and looks professional. Text size also needs discipline: names at 14–16pt, titles at 9–11pt, and contact lines at 7.5–9pt form a hierarchy that stays legible at the physical size of a card.
dompdf.js supports flex and grid layouts, so common card structures — left-right split, vertically centered, or two-sided designs — can all be built with modern CSS. Fidelity is far higher than traditional coordinate-based PDF libraries, and redesigns are just template edits. Line spacing matters as much as size: generous leading between contact lines keeps a dense card scannable, while cramped rows undo the work of good typography.
Contrast is the quiet hero of card design. Dark text on a light background prints reliably on every office printer, while reverse-type (light text on dark) demands a print shop; keep critical contact information in high-contrast form and reserve decorative treatments for the logo area.
Two-sided cards are handled naturally: the front and back are simply two page regions, and the same data loop can render the back with a different template, such as a QR code, a map, or a list of services.
When cards are destined for a commercial printer, ask for the exact bleed and safe-area specifications before designing the template. Building those numbers into the CSS from the start avoids a rework cycle later.
Personnel data usually comes from an HR system or a spreadsheet import. The frontend receives an array and fills the template in a loop. Always HTML-escape fields like names and company names so characters such as &, <, and > cannot break the template structure and cause rendering errors. Escaping is not optional: a single ampersand in a company name such as 'Smith & Sons' can break the HTML parse and corrupt the whole page, so route every data field through an escape helper before interpolation.
Company logos and QR codes can be embedded as images: dompdf.js supports bitmaps, SVGs, and data URLs. A logo can be a base64 string or a hosted URL, so templates are self-contained and can even generate PDFs offline. For data that arrives from Excel or CSV, normalize the field order and trim whitespace on import; the template then assumes a stable schema and renders without surprises.
For very large batches (hundreds of cards), add pages in smaller groups and show progress feedback. Rendering runs in a Web Worker, so the page stays responsive during export and users never see a frozen interface while waiting. Consistent data types also prevent subtle bugs — storing phone numbers as text rather than numbers preserves leading zeros and formatting that a spreadsheet would otherwise destroy.
Image handling deserves a little planning as well. Logos are best embedded as SVG or a modestly sized PNG, and reusing the same image object across cards keeps memory usage flat instead of re-decoding the image for every page.
If personnel data changes after a batch has been exported, the frontend flow makes regeneration trivial: re-run the same loop with updated data and the corrected PDF replaces the old one in seconds, which is a major advantage over print shops that charge for re-runs.
For security-conscious environments, everything can stay in the browser: personnel data never leaves the user's machine during generation, which simplifies compliance with internal data-handling policies.
Q: Will Chinese characters be garbled in the generated PDF? A: No. The built-in Source Han Sans SC font renders proper Chinese without configuration. If your company requires a specific typeface, embed the font file explicitly through font configuration. The built-in font covers the common range of Simplified Chinese characters; if your card includes traditional characters, minority scripts, or special symbols, embed the matching font to guarantee coverage.
Q: Can I put a QR code on the card? A: Yes. QR codes embed like any regular image and stay sharp in vector output, so phone scanning is unaffected — ideal for electronic business cards. Keep the QR code at least 20mm by 20mm and leave quiet-zone whitespace around it so scanners at print resolution still read it reliably.
Q: How fast is batch export? A: The Rust+WASM core is fast; batches of a hundred cards complete in seconds. It is still wise to guard the export button against double-clicks so users cannot accidentally generate duplicate files. A good pattern is to disable the button, show a spinner, and re-enable it after save resolves; the whole batch typically completes before the user notices.
Q: Can the same template produce cards in different languages? A: Yes — keep the layout in the template and the text in the data. Switch the data array (or a language field) and the same template renders English, Chinese, or any language whose font you embed.
Q: What if the customer wants a different card size, such as 85mm by 55mm or a square format? A: Change the width and height in the template CSS; pagination and centering adjust automatically because layout derives from the container, not from hard-coded coordinates.
下面的按钮用 dompdf.js 在浏览器端实时生成 PDF,无需后端:
这是由 dompdf.js 渲染的示例 PDF 内容。