How to add a print or PDF button to any website
Paste a single anchor tag that opens the current URL in a printer-friendly view, or a button element calling window.print(). Both are a few lines of plain HTML and work in any CMS or static site. Hide the button in @media print, and use the anchor form inside Wix, where embeds are iframes.
A print button is one HTML element. Every plugin, widget and paid service on this subject is packaging around that element. Below are the two versions worth using, when each applies, and where to paste them in the platforms that make it awkward.
Decide what the button should do first
| Behaviour | What it needs from you | Best for |
|---|---|---|
window.print() on the current page | A print stylesheet you have written and tested | Login-gated pages: orders, accounts, dashboards, invoices |
| Open the URL in a printer-friendly view | Nothing. The cleaner does the layout work | Public pages, especially when you have no print CSS yet |
| Both, side by side | A stylesheet, plus one extra link | Publishers who want a paper option and a PDF option |
If you have not written print CSS, the second option is strictly better today and you can add the first later. If your page is behind a login, the second option cannot work at all: a cleaner fetching that URL gets the sign-in screen, not the order.
Version 1: the plain anchor
No framework, no build step, no dependency. It degrades gracefully: with JavaScript disabled it still opens the cleaner, just without the current URL prefilled.
<!-- Printer-friendly link. Paste anywhere HTML is allowed. -->
<a class="pxp-print"
href="https://printxpdf.com/print?url="
onclick="this.href='https://printxpdf.com/print?url='+encodeURIComponent(location.href)"
target="_blank" rel="noopener">⎙ Print / PDF</a>
<style>
.pxp-print{display:inline-flex;align-items:center;gap:.5rem;padding:10px 18px;
font:700 14px/1 system-ui,-apple-system,sans-serif;letter-spacing:.03em;
text-decoration:none;color:inherit;border:2px solid currentColor;border-radius:6px}
.pxp-print:hover{background:currentColor;color:#fff}
@media print{.pxp-print{display:none !important}}
</style>encodeURIComponent is the part people leave out, and it is why buttons break on pages with query strings or accented characters in the path. The @media print rule at the bottom is the part everyone leaves out, and it is why printed pages have a "Print" button printed on them.
Version 2: window.print(), CSP-safe
If your site sends a strict Content-Security-Policy header, an inline onclick will be blocked and the button will silently do nothing. Attach a listener instead. Use a real <button type="button">, not an anchor with a javascript: href: buttons are keyboard-operable and announced correctly by screen readers, and type="button" stops it submitting a surrounding form.
<button type="button" class="pxp-print" data-print-page>
⎙ Print this page
</button>
<script>
document.querySelectorAll('[data-print-page]').forEach(function (btn) {
btn.addEventListener('click', function () {
window.print();
});
});
// Optional: expand collapsed sections before the dialog paints
window.addEventListener('beforeprint', function () {
document.querySelectorAll('details').forEach(function (d) { d.open = true; });
});
</script>To open the cleaner from a button instead of an anchor, swap the click handler for window.open('https://printxpdf.com/print?url=' + encodeURIComponent(location.href), '_blank', 'noopener').
Do not ship an icon on its own. A printer glyph with no label is unrecognisable to a good number of readers under thirty, who have never used one. Label it "Print / PDF", and if you must go icon-only, add an aria-label.
Where to paste it, platform by platform
| Platform | Where it goes | Gotcha |
|---|---|---|
| Static site (Hugo, Jekyll, Eleventy, Astro) | The post layout partial, next to the title or after the content | None. Put it in the layout once and every page has it |
| Squarespace | A Code Block where you want the button | Site-wide code injection needs a Business plan or higher; a per-page Code Block does not |
| Wix | Add → Embed Code → Embed HTML | The embed is an iframe, so window.print() prints only the empty embed. Use the anchor version |
| Webflow | An Embed element in the Designer | Embeds render inline, not in an iframe, so both versions work |
| Shopify | sections/main-article.liquid or main-page.liquid | Use Liquid to build the URL: {{ canonical_url | url_encode }} |
| Ghost | The post template, or a Code Injection block | Handlebars gives you the absolute URL: {{url absolute="true"}} |
| Email templates | The anchor version only | No JavaScript runs in email. Hard-code the article URL into the href |
| Notion, Substack, Medium | Not possible | No custom HTML. Link to the cleaner with the URL written out in full |
The Wix case is worth spelling out because it wastes a lot of afternoons. Wix HTML embeds run inside an iframe on a different origin. Calling window.print() there prints the iframe, which contains nothing but your button, and parent.print() is blocked by the same-origin policy. The anchor, which simply navigates a new tab, is unaffected.
Putting it in place
- Pick the behaviourCleaner link for public pages with no print CSS.
window.print()for login-gated pages, or for public pages where you have already written and tested a stylesheet. - Paste it into the template, not the pageOne edit in a layout beats fifty edits in fifty posts. On a hosted CMS, use a synced pattern, a reusable block or a saved section so there is still one source of truth.
- Place it where the decision happensNear the title for recipes, tickets and receipts. At the end as well for long articles, which is where a reader decides the piece is worth keeping.
- Hide it on paperAdd
@media print { .pxp-print { display: none !important } }. Do this now, because you will not notice it until a reader mentions it. - Check the keyboard and the screen readerTab to it, press Enter, and confirm it announces as a link or a button with a real name.
type="button"on buttons,rel="noopener"on anchors withtarget="_blank". - Print the result and read itDo not ship on the strength of the preview thumbnail. Print one page, or save it as a PDF and read it at full size.
Check what your page really produces on paper before you put a button on it.
HTML to PDF →Generate one instead of writing it
If you would rather pick a colour, size and label than edit CSS, the button builder produces the same markup with inline styles, ready to paste into any CMS. On WordPress specifically, the plugin, block and shortcode routes cover the options in more detail, and the WordPress plugin page has the one-click version.
Add a QR code so the printed sheet still leads back to the live page.
QR Code Generator →A button without a stylesheet is only half a feature. When you have the button in place, spend an afternoon on a print stylesheet and run the printer-friendly checklist over your main templates.
Frequently asked questions
What is the HTML code for a print button?
The minimum is <button type="button" onclick="window.print()">Print</button>. Use type="button" so it never submits a surrounding form, and add a @media print rule hiding the button, or it prints on the page itself.
Should I use a link or a button for printing?
A button element when it triggers window.print(), because it performs an action on the current page. An anchor when it navigates somewhere, such as opening the page in a printer-friendly view in a new tab. Do not use an anchor with a javascript: href.
Why does my print button not work on Wix?
Wix HTML embeds run inside an iframe, so window.print() prints the empty embed rather than the page, and parent.print() is blocked cross-origin. Use the anchor version, which opens the page URL in a new tab instead.
How do I pass the current page URL to a print tool?
Append it as an encoded query parameter: encodeURIComponent(location.href) in JavaScript, or the url_encode filter in Shopify Liquid. Encoding matters because raw query strings and accented characters break the link.
Does a print button need JavaScript?
Not if it is an anchor pointing at a printer-friendly view, which works with scripting disabled. It does if it calls window.print(). The anchor version is also the only one that works inside an email template.