{"id":11412,"date":"2024-03-05T22:18:36","date_gmt":"2024-03-05T21:18:36","guid":{"rendered":"https:\/\/monodes.com\/predaelli\/?p=11412"},"modified":"2024-03-05T22:19:38","modified_gmt":"2024-03-05T21:19:38","slug":"css-for-printing-to-paper","status":"publish","type":"post","link":"https:\/\/monodes.com\/predaelli\/2024\/03\/05\/css-for-printing-to-paper\/","title":{"rendered":"CSS for printing to paper"},"content":{"rendered":"\n<p><em><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/\">CSS for printing to paper<\/a><\/em><\/p>\n\n\n\n<p>I do like articles explaining how to use CSS for printing!<\/p>\n\n\n\n<!--more-->\n\n\n\n<!--nextpage-->\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<h1 class=\"wp-block-heading\">CSS for printing to paper<\/h1>\n\n\n\n<ol class=\"wp-block-list\">\n<li><\/li>\n<\/ol>\n\n\n\n<ol class=\"wp-block-list\" id=\"table_of_contents\">\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#introduction\">Introduction<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#sample_files\">Sample files<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#page\">@page<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#media_print\">@media print<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#width_height_margin_and_padding\">Width, height, margin, and padding<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#element_positioning\">Element positioning<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#multipage_documents_with_repeating_elements\">Multi-page documents with repeating elements<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#portrait_landscape_mode\">Portrait \/ Landscape mode<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#data_source\">Data source<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/#essentials_cheatsheet\">Essentials cheatsheet<\/a><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>At work, one of the things I do pretty often is write print generators in HTML to recreate and replace forms that the company has traditionally done handwritten on paper or in Excel. This allows the company to move into new web-based tools where the form is autofilled by URL parameters from our database, while getting the same physical output everyone&#8217;s familiar with.<\/p>\n\n\n\n<p>This article explains some of the CSS basics that control how your webpages look when printed, and a couple of tips and tricks I&#8217;ve learned that might help you out.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sample files<\/h2>\n\n\n\n<p>Here are some sample page generators to establish some context, and perhaps a shred of credibility.<\/p>\n\n\n\n<p>I&#8217;ll be the first to admit these pages are a little bit ugly and could use more polish. But they get the job done and I&#8217;m still employed.<\/p>\n\n\n\n<p><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/sample_invoice.html\">Invoice generator<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/sample_sidebar.html?jobno=BRAINIACS&amp;commissioner=Minister%20McMinisterface&amp;medium=film&amp;execproducer=Golan%20%26%20Globus&amp;color=B\/W&amp;director=Peter%20Jackson&amp;length=80m&amp;funding=80%%20benefactor;%2020%%20panhandling&amp;budget=$1,234,567.00&amp;jobcontactname=Taylor%20Shift&amp;jobcontactphone=555-123-4567&amp;jobcontactemail=production@voussoir.net&amp;unioncontact=Richard%20Pryor&amp;union=TAAGSRFA&amp;synopsis=A%20group%20of%20ten%20quirky%20teenagers%20from%20opposite%20ends%20of%20town%20awaken%20one%20morning%20to%20find%20themselves%20in%20an%20unrecognizable%20world.%20All%20their%20friends%20and%20family%20are%20chasing%20them%20with%20sawed-off%20shotguns%20and%20flamethrowers.%20The%20group%20realizes%20they%20need%20to%20overcome%20their%20differences%20and%20work%20together%20if%20they%20want%20to%20have%20any%20chance%20of%20ending%20the%20human%20race%20and%20eating%20all%20the%20brains.%20Rated%20G.&amp;principlephoto=2024-06-01&amp;wrapdate=2024-06-03&amp;talent=Molly%20Ringwald%20as%20Claire%0AAngus%20Scrimm%20as%20Tiny%20Tim%0ASteve%20McQueen%20as%20Chadster%0AKeith%20David%20as%20Frank%20Armitage%0Alocal%20pigeon%20as%20The%20Great%20Destroyer%0AMichael%20Beck%20as%20Swan%0ADavid%20Cronenberg%20as%20himself&amp;payfreq=weekly&amp;otrate=1.1x&amp;dtrate=1.15x&amp;payrollcontact=shredpile@voussoir.net&amp;remarks=Please%20try%20to%20get%20Tom%20Cruise%20in%20the%20promotional%20material%20because%20we%20need%20something%20to%20draw%20crowds.&amp;signedby=voussoir&amp;signeddate=2024-02-29\">Coversheet with sidebar inputs<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/sample_contenteditable.html?missionnumber=ABC123&amp;victimname=Minister%20McMinisterface&amp;dob=1970-01-01&amp;occupation=Prime%20Minister%20of%20Governmentown&amp;maritalstatus=Divorced%20once%20removed&amp;language=en_CA-eh&amp;children=9&amp;issuedate=2024-02-27&amp;duedate=2024-07-04&amp;customerrequest=I%20want%20McMinisterface%20to%20experience%20a%20pranking%20the%20likes%20of%20which%20he%27s%20never%20seen%20and%20will%20never%20see%20again&amp;catalogno=GOT-UR-NOSE&amp;catalogvar=yogababe&amp;catalogsubvar=downwarddog&amp;specifics=At%20precisely%200604%20hours,%20as%20McMinisterface%20is%20heading%20out%20the%20front%20door%20of%20his%20flat%20carrying%20a%20breakfast%20scone%20and%20that%20stupid%20yellow%20coffee%20mug,%20the%20Operative%20shall%20place%20himself%20in%20front%20of%20the%20door%20of%20the%20flat,%20assuming%20the%20Downward%20Dog%20position,%20rendering%20him%20undetectable%20to%20all%20passersby.%20McMinisterface%20will%20unexpectedly%20trip%20over%20the%20firmly%20planted%20body%20of%20the%20Operative,%20landing%20on%20the%20concrete,%20breaking%20the%20cartilage%20in%20his%20nose%20and%20dropping%20that%20stupid%20yellow%20coffee%20mug.%20The%20Operative%20will%20approach%20the%20fallen%20McMinisterface%20and%20offer%20to%20help%20him%20up,%20but%20at%20the%20last%20minute%20say%20YOINK,%20GOT%20YOUR%20NOSE%20and%20run%20towards%20the%20bus%20station%20at%20the%20corner%20of%20First%20and%201st%20to%20catch%20the%200606%20bus%20for%20a%20timely%20escape.&amp;callsick=1&amp;leavephone=1&amp;scheduleddelivery=Anti-itch%20ointment,%20to%20be%20left%20on%20porch%20because%20too%20embarrassed%20to%20make%20knowing%20eye%20contact%20with%20delivery%20person&amp;leaveotherphone=1&amp;leaveotherotherphone=0&amp;soundeffects=snoring;%20groaning;%20leavemealone%20120min%20loop&amp;jointeffort=0&amp;jointopname=NA&amp;jointlocation=NA&amp;jointtime=NA&amp;leavehome=0430&amp;leavecafe=0545&amp;arrivesite=0602&amp;getaway=0606&amp;laylow=72hr%20minimum\">Coversheet with contenteditable<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/sample_qr.html\">QR code generator<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">@page<\/h2>\n\n\n\n<p>CSS has a rule called <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/@page\"><code class=\"\" data-line=\"\">@page<\/code><\/a> that informs the browser of your website&#8217;s printing preferences. Normally, I use<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>I will explain why I choose <code class=\"\" data-line=\"\">margin: 0<\/code> in the later section about margins. You should use Letter or A4 as appropriate for your relationship with the metric system.<\/p>\n\n\n\n<p>Setting the size and margin of @page is not the same as setting the width, height, and margin of your <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> or <code class=\"\" data-line=\"\">&lt;body&gt;<\/code> element. @page is beyond the DOM \u2014 it contains the DOM. On the web, your <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> element is bounded by the edges of your screen, but when printing it is bounded by @page.<\/p>\n\n\n\n<p>The settings controlled by @page more or less correspond to the settings you get in your browser&#8217;s print dialog when you press Ctrl+P.<\/p>\n\n\n\n<p>Here&#8217;s a sample file I used to do some experiments:<\/p>\n\n\n\n<div class=\"highlight html\">\n<pre><span class=\"cp\">&lt;!DOCTYPE html&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"nt\">html<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"c\">\/* see below for each experiment *\/<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">html<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mi\">100<\/span><span class=\"kt\">%<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">100<\/span><span class=\"kt\">%<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">background-color<\/span><span class=\"p\">:<\/span> <span class=\"kc\">lightblue<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"c\">\/* grid by shunryu111 https:\/\/stackoverflow.com\/a\/32861765\/5430534 *\/<\/span>\n    <span class=\"k\">background-size<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.25<\/span><span class=\"kt\">in<\/span> <span class=\"mf\">0.25<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">background-image<\/span><span class=\"p\">:<\/span>\n    <span class=\"nb\">linear-gradient<\/span><span class=\"p\">(<\/span><span class=\"kc\">to<\/span> <span class=\"kc\">right<\/span><span class=\"p\">,<\/span> <span class=\"kc\">gray<\/span> <span class=\"mi\">1<\/span><span class=\"kt\">px<\/span><span class=\"p\">,<\/span> <span class=\"kc\">transparent<\/span> <span class=\"mi\">1<\/span><span class=\"kt\">px<\/span><span class=\"p\">)<\/span><span class=\"p\">,<\/span>\n    <span class=\"nb\">linear-gradient<\/span><span class=\"p\">(<\/span><span class=\"kc\">to<\/span> <span class=\"kc\">bottom<\/span><span class=\"p\">,<\/span> <span class=\"kc\">gray<\/span> <span class=\"mi\">1<\/span><span class=\"kt\">px<\/span><span class=\"p\">,<\/span> <span class=\"kc\">transparent<\/span> <span class=\"mi\">1<\/span><span class=\"kt\">px<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"\">sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">html<\/span><span class=\"p\">&gt;<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>Here&#8217;s how that looks in the browser:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/sample_in_browser.png?w=910&#038;ssl=1\" alt=\"\" title=\"but i don't want new chrome\"\/><\/figure>\n\n\n\n<p>And here are the results of some different @page values:<\/p>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: Letter portrait; margin: 1in; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/letter_portrait_1in.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: Letter landscape; margin: 1in; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/letter_landscape_in1.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: Letter landscape; margin: 0; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/letter_landscape_0.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>Setting the @page size won&#8217;t actually put that size of paper into your printer&#8217;s feed tray. <a title=\"Office Space - PC Load Letter?\" href=\"https:\/\/youtu.be\/3z9YjGWaxC0\">You&#8217;ll have to do that part yourself<\/a>.<\/p>\n\n\n\n<p>Notice how when I set <code class=\"\" data-line=\"\">size<\/code> to A5, my printer stays on Letter, and the A5 size fits entirely within the Letter size which gives the appearance of a margin even though it&#8217;s not coming from the <code class=\"\" data-line=\"\">margin<\/code> setting.<\/p>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: A5 portrait; margin: 0; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/a5_portrait_0.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>But if I tell the printer that I have actual A5 paper loaded, then it looks as expected.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/a5_portrait_0_a5paper.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>From what I gather by experimentation, Chrome only follows the @page rule if you have Margin set to Default. As soon as you change Margin in the print dialog, your output is instead the product of your physical paper size and the chosen margin.<\/p>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: A5 portrait; margin: 0; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/a5_portrait_0_default.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/a5_portrait_0_none.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>Even when you choose a @page size that fits fully within your physical paper, the <code class=\"\" data-line=\"\">margin<\/code> still matters. Here, I make a 5&#215;5 square with no margin, and a 5&#215;5 square with margin. The size of the <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> element is bounded by the @page size <strong>and<\/strong> margin combined.<\/p>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: 5in 5in; margin: 0; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/5in_5in_0.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p><code class=\"\" data-line=\"\">@page { size: 5in 5in; margin: 1in; }<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/5in_5in_1in.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>I did all these tests not because I expect to print on A5 or 5&#215;5 paper, but because it took me a while to figure out what exactly @page is. Now I am pretty confident in always using Letter with margin 0.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">@media print<\/h2>\n\n\n\n<p>There is a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/@media\">media query<\/a> called <code class=\"\" data-line=\"\">print<\/code> where you can write styles that only apply during printing. My generator pages often contain a header, some options, and some help text for the user that obviously shouldn&#8217;t come out on the print, so this is where you add <code class=\"\" data-line=\"\">display:none<\/code> on those elements.<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"c\">\/* Normal styles that appear while you are preparing the document *\/<\/span>\n<span class=\"nt\">header<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">display<\/span><span class=\"p\">:<\/span> <span class=\"kc\">block<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">@<\/span><span class=\"k\">media<\/span> <span class=\"nt\">print<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"c\">\/* Disappear when you are printing the document *\/<\/span>\n    <span class=\"nt\">header<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">display<\/span><span class=\"p\">:<\/span> <span class=\"kc\">none<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/mediaprint_1.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/mediaprint_2.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Width, height, margin, and padding<\/h2>\n\n\n\n<p>You&#8217;ll need to know a bit about the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/CSS\/Building_blocks\/The_box_model\">box model<\/a> to get the margins you want without wrestling the computer too much.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/CSS\/Building_blocks\/The_box_model\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/box_model.png?w=910&#038;ssl=1\" alt=\"\"\/><\/a><\/figure>\n\n\n\n<p>The reason I always set @page <code class=\"\" data-line=\"\">margin: 0<\/code> is that I&#8217;d rather handle the margins on the DOM elements instead. When I tried to use @page <code class=\"\" data-line=\"\">margin: 0.5in<\/code>, I would often accidentally wind up with double-margins that squash the content smaller than I expected, and my one-page design spilled onto a second page.<\/p>\n\n\n\n<p>If I wanted to use @page margin, then the actual page content would need to be laid out all the way up against the edges of the DOM, which is harder for me to think about and harder to preview before printing. It is mentally easier for me to remember that <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> occupies the entire physical paper and my margins are within the DOM instead of beyond it.<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">html<\/span><span class=\"n\">,<\/span>\n<span class=\"nt\">body<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>When it comes to multi-page print generators, you&#8217;re going to want a separate DOM element representing each page. Since you can&#8217;t have multiple <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> or <code class=\"\" data-line=\"\">&lt;body&gt;<\/code>, you&#8217;re going to need another element. I like <code class=\"\" data-line=\"\">&lt;article&gt;<\/code>. Even for single-page generators, you may as well always use an article.<\/p>\n\n\n\n<p>Since each <code class=\"\" data-line=\"\">&lt;article&gt;<\/code> represents one page, I don&#8217;t want any margins or padding on <code class=\"\" data-line=\"\">&lt;html&gt;<\/code> or <code class=\"\" data-line=\"\">&lt;body&gt;<\/code>. We&#8217;re pushing the logic one step further \u2014 it is easier for me to let the article occupy the entire physical page and put my margins within it.<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">html<\/span><span class=\"n\">,<\/span>\n<span class=\"nt\">body<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">article<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>When I talk about adding margin within my article, I&#8217;m not using the <code class=\"\" data-line=\"\">margin<\/code> property, I&#8217;m using <code class=\"\" data-line=\"\">padding<\/code>. That&#8217;s because <code class=\"\" data-line=\"\">margin<\/code> goes outside and around your element in the box model. If you use a <code class=\"\" data-line=\"\">margin<\/code> of 0.5in, you&#8217;ll have to set the article to 7.5\u00d710 so that the article plus 2\u00d7margin equals 8.5\u00d711. And if you want to adjust that margin you&#8217;ll have to adjust the other dimensions.<\/p>\n\n\n\n<p>Instead, <code class=\"\" data-line=\"\">padding<\/code> goes on the inside of the element, so I can define the article to be 8.5\u00d711 with 0.5in padding, and all the elements inside the article will stay on the page.<\/p>\n\n\n\n<p>A lot of intuition about element dimensions is easier when you set <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/box-sizing\"><code class=\"\" data-line=\"\">box-sizing: border-box<\/code><\/a>. It makes it so that the outer dimensions of the article are locked in while you adjust the inner padding. This is my snippet:<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"nt\">html<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">border-box<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"o\">*<\/span><span class=\"n\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">before<\/span><span class=\"nd\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">after<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">inherit<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>Let&#8217;s put this all together:<\/p>\n\n\n\n<div class=\"highlight css\">\n<pre><span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">html<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">border-box<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"o\">*<\/span><span class=\"n\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">before<\/span><span class=\"nd\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">after<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">inherit<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">html<\/span><span class=\"n\">,<\/span>\n<span class=\"nt\">body<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">article<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">padding<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/margins_padding.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Element positioning<\/h2>\n\n\n\n<p>Once you&#8217;ve got your articles and margins set up, the space inside the article is yours to do with as you please. Design your document using whatever HTML\/CSS you feel is appropriate for the project. Sometimes this means laying out elements with flex or grid because you&#8217;ve been given some leeway with the output. Sometimes it means creating squares of a specific size to fit on a certain brand of sticker paper. Sometimes it means absolutely positioning absolutely everything to the millimeter because the user needs to feed a special piece of pre-labeled paper through the printer to get your data on top of it, and you&#8217;re not in control of that special paper.<\/p>\n\n\n\n<p>I&#8217;m not here to give a tutorial on how to write HTML in general, so you&#8217;ll need to be able to do that. All I can say is be mindful of that fact that you&#8217;re dealing with the limited real estate of a piece of paper, unlike a browser window which can scroll and zoom to any length or scale. If your document will contain an arbitrary number of items, be ready to paginate by creating more <code class=\"\" data-line=\"\">&lt;article&gt;<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Multi-page documents with repeating elements<\/h2>\n\n\n\n<p>A lot of the print generators I write contain tabular data, like an invoice full of line items. If your <code class=\"\" data-line=\"\">&lt;table&gt;<\/code> is large enough to go onto a second page, the browser will automatically duplicate the <code class=\"\" data-line=\"\">&lt;thead&gt;<\/code> at the top of each page.<\/p>\n\n\n\n<div class=\"highlight html\">\n<pre><span class=\"p\">&lt;<\/span><span class=\"nt\">table<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">thead<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">thead<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">tbody<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">0<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">0<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">1<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">1<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">2<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"\">4<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span><span class=\"\">\n        ...\n    <\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">tbody<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">table<\/span><span class=\"p\">&gt;<\/span>\n<\/pre>\n<\/div>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2024\/03\/multipage_table_1.png?w=910&#038;ssl=1\" alt=\"\"\/><\/figure>\n\n\n\n<p>That&#8217;s great if you&#8217;re just printing a <code class=\"\" data-line=\"\">&lt;table&gt;<\/code> with no frills, but in a lot of real scenarios it&#8217;s not that simple. The document I&#8217;m recreating often has a letterhead on the top of each page, a footer on the bottom, and other custom elements that need to be explicitly repeated on each page. If you just print a single long table across pages, you don&#8217;t have much ability to place other elements above, below, and around it on intermediate pages.<\/p>\n\n\n\n<p>So, I generate the pages using javascript, splitting the table into several smaller ones. The general approach here is this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Treat the <code class=\"\" data-line=\"\">&lt;article&gt;<\/code> elements as disposable and be ready to regenerate them at any time from objects in memory. All user input and configuration should take place in a separate header \/ options box, outside of the articles.<\/li>\n\n\n\n<li>Write a function called <code class=\"\" data-line=\"\">new_page<\/code> that creates a new article element with the necessary repeating header\/footer\/etc.<\/li>\n\n\n\n<li>Write a function called <code class=\"\" data-line=\"\">render_pages<\/code> that creates the articles from the base data, calling <code class=\"\" data-line=\"\">new_page<\/code> every time it fills up the previous one. I usually use <code class=\"\" data-line=\"\">offsetTop<\/code> to see when the content is getting far along the page, though you could <strong>definitely<\/strong> use smarter techniques to get the perfect fit on each page.<\/li>\n\n\n\n<li>Call <code class=\"\" data-line=\"\">render_pages<\/code> whenever the base data changes.<\/li>\n<\/ol>\n\n\n\n<div class=\"highlight javascript\">\n<pre><span class=\"kd\">function<\/span> <span class=\"nx\">delete_articles<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">article<\/span> <span class=\"k\">of<\/span> <span class=\"nb\">Array<\/span><span class=\"p\">.<\/span><span class=\"kr\">from<\/span><span class=\"p\">(<\/span><span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementsByTagName<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"article\"<\/span><span class=\"p\">)<\/span><span class=\"p\">)<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">body<\/span><span class=\"p\">.<\/span><span class=\"nx\">removeChild<\/span><span class=\"p\">(<\/span><span class=\"nx\">article<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nx\">new_page<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">article<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">createElement<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"article\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">article<\/span><span class=\"p\">.<\/span><span class=\"nx\">innerHTML<\/span> <span class=\"o\">=<\/span> <span class=\"sb\">`<\/span><span class=\"sb\">\n    &lt;header&gt;...&lt;\/header&gt;\n    &lt;table&gt;...&lt;\/table&gt;\n    &lt;footer&gt;...&lt;\/footer&gt;\n    <\/span><span class=\"sb\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">body<\/span><span class=\"p\">.<\/span><span class=\"nx\">append<\/span><span class=\"p\">(<\/span><span class=\"nx\">article<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">article<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nx\">render_pages<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nx\">delete_articles<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">let<\/span> <span class=\"nx\">page<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">new_page<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">let<\/span> <span class=\"nx\">tbody<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"table tbody\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">line_item<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">line_items<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ I usually pick this threshold by experimentation but you can probably<\/span>\n        <span class=\"c1\">\/\/ do something more rigorously correct.<\/span>\n        <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">tbody<\/span><span class=\"p\">.<\/span><span class=\"nx\">offsetTop<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">tbody<\/span><span class=\"p\">.<\/span><span class=\"nx\">offsetParent<\/span><span class=\"p\">.<\/span><span class=\"nx\">offsetTop<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mf\">900<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">{<\/span>\n            <span class=\"nx\">page<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">new_page<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n            <span class=\"nx\">tbody<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"table tbody\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">tr<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">createElement<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"tr\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n        <span class=\"nx\">tbody<\/span><span class=\"p\">.<\/span><span class=\"nx\">append<\/span><span class=\"p\">(<\/span><span class=\"nx\">tr<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n        <span class=\"c1\">\/\/ ...<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>It is usually good to include a &#8220;page X of Y&#8221; counter on your pages. Since the number of pages is not known until all pages are generated, I can&#8217;t do this during the for loop. I call a function like this at the end:<\/p>\n\n\n\n<div class=\"highlight javascript\">\n<pre><span class=\"kd\">function<\/span> <span class=\"nx\">renumber_pages<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"kd\">let<\/span> <span class=\"nx\">pagenumber<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">1<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">pages<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementsByTagName<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"article\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">page<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">pages<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">querySelector<\/span><span class=\"p\">(<\/span><span class=\"s2\">\".pagenumber\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">innerText<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">pagenumber<\/span><span class=\"p\">;<\/span>\n        <span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">querySelector<\/span><span class=\"p\">(<\/span><span class=\"s2\">\".totalpages\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">innerText<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">pages<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span>\n        <span class=\"nx\">pagenumber<\/span> <span class=\"o\">+=<\/span> <span class=\"mf\">1<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Portrait \/ Landscape mode<\/h2>\n\n\n\n<p>I&#8217;ve shown that the @page rule helps inform the browser&#8217;s default print settings, but the user can override it if they want to. If you set @page to portrait mode and the user overrides it to landscape mode, your layout and pagination might look wrong, especially if you are hardcoding any page thresholds.<\/p>\n\n\n\n<p>You can accommodate them by creating separate <code class=\"\" data-line=\"\">&lt;style&gt;<\/code> elements for portrait and landscape, and using javascript to switch between them. There might be a better way to do this, but at-rules like @page behave differently than normal CSS properties so I&#8217;m not sure. You should also save some variable that can help your <code class=\"\" data-line=\"\">render_pages<\/code> function do the right thing.<\/p>\n\n\n\n<p>You could also stop hardcoding thresholds, but then I&#8217;d have to follow my own advice.<\/p>\n\n\n\n<div class=\"highlight html\">\n<pre><span class=\"p\">&lt;<\/span><span class=\"nt\">select<\/span> <span class=\"na\">onchange<\/span><span class=\"o\">=<\/span><span class=\"s\">\"return page_orientation_onchange(event);\"<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span> <span class=\"na\">selected<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Portrait<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Landscape<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">select<\/span><span class=\"p\">&gt;<\/span>\n<\/pre>\n<\/div>\n\n\n\n<div class=\"highlight html\">\n<pre><span class=\"p\">&lt;<\/span><span class=\"nt\">style<\/span> <span class=\"na\">id<\/span><span class=\"o\">=<\/span><span class=\"s\">\"style_portrait\"<\/span> <span class=\"na\">media<\/span><span class=\"o\">=<\/span><span class=\"s\">\"all\"<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">article<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n\n<span class=\"p\">&lt;<\/span><span class=\"nt\">style<\/span> <span class=\"na\">id<\/span><span class=\"o\">=<\/span><span class=\"s\">\"style_landscape\"<\/span> <span class=\"na\">media<\/span><span class=\"o\">=<\/span><span class=\"s\">\"not all\"<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">landscape<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">article<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n<\/pre>\n<\/div>\n\n\n\n<div class=\"highlight javascript\">\n<pre><span class=\"kd\">let<\/span> <span class=\"nx\">print_orientation<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"portrait\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nx\">page_orientation_onchange<\/span><span class=\"p\">(<\/span><span class=\"nx\">event<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nx\">print_orientation<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nx\">toLocaleLowerCase<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">print_orientation<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"portrait\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"style_portrait\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">setAttribute<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"media\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"all\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n        <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"style_landscape\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">setAttribute<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"media\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"not all\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">print_orientation<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"landscape\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"style_landscape\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">setAttribute<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"media\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"all\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n        <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"style_portrait\"<\/span><span class=\"p\">)<\/span><span class=\"p\">.<\/span><span class=\"nx\">setAttribute<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"media\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"not all\"<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nx\">render_printpages<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nx\">render_printpages<\/span><span class=\"p\">(<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">print_orientation<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"portrait\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ ...<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">else<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ ...<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Data source<\/h2>\n\n\n\n<p>There are a couple of ways to get your data onto the page. Sometimes, I pack all of the data into the URL parameters, so the javascript just does <code class=\"\" data-line=\"\">const url_params = new URLSearchParams(window.location.search);<\/code> and then a bunch of <code class=\"\" data-line=\"\">url_params.get(&quot;title&quot;)<\/code>. This has some advantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The page loads very fast.<\/li>\n\n\n\n<li>It&#8217;s easy to debug and experiment by changing the URL.<\/li>\n\n\n\n<li>The generator works offline.<\/li>\n<\/ul>\n\n\n\n<p>This also has some disadvantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The URLs become very long and unweildy, people cannot comfortably email them to each other. See sample links at the top of this article.<\/li>\n\n\n\n<li>If the URL does get sent in an email, that data is &#8220;locked in&#8221;, even if the source record in your database changes later.<\/li>\n\n\n\n<li>Browsers do have limits on URL length. The limits are pretty high but not infinite and might vary per client.<\/li>\n<\/ul>\n\n\n\n<p>Sometimes I instead use javascript to fetch our database records over the API, so the URL parameters just contain the record&#8217;s primary key and maybe a mode setting.<\/p>\n\n\n\n<p>This has some advantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The URLs are much shorter.<\/li>\n\n\n\n<li>The data is always fresh.<\/li>\n<\/ul>\n\n\n\n<p>and disadvantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The user has to wait a second while the data is being fetched.<\/li>\n\n\n\n<li>You have to write more code.<\/li>\n<\/ul>\n\n\n\n<p>Sometimes I set <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Global_attributes\/contenteditable\"><code class=\"\" data-line=\"\">contenteditable<\/code><\/a> on the articles so the user can make small changes before printing. I also like to use real, live checkbox inputs they can click before printing. These features add some convenience, but in most cases it would be wiser to make the user change the source record in the database first. Also, they limit your ability to treat the article elements as disposable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Essentials cheatsheet<\/h2>\n\n\n\n<p><a href=\"https:\/\/voussoir.net\/writing\/css_for_printing\/sample_cheatsheet.html\">sample_cheatsheet.html<\/a><\/p>\n\n\n\n<div class=\"highlight html\">\n<pre><span class=\"cp\">&lt;!DOCTYPE html&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"nt\">html<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">@<\/span><span class=\"k\">page<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">size<\/span><span class=\"o\">:<\/span> <span class=\"nt\">Letter<\/span> <span class=\"nt\">portrait<\/span><span class=\"n\">;<\/span>\n    <span class=\"nt\">margin<\/span><span class=\"o\">:<\/span> <span class=\"nt\">0<\/span><span class=\"n\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nt\">html<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">border-box<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"o\">*<\/span><span class=\"n\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">before<\/span><span class=\"nd\">,<\/span> <span class=\"o\">*<\/span><span class=\"p\">:<\/span><span class=\"nd\">after<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">box-sizing<\/span><span class=\"p\">:<\/span> <span class=\"kc\">inherit<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">html<\/span><span class=\"n\">,<\/span>\n<span class=\"nt\">body<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">background-color<\/span><span class=\"p\">:<\/span> <span class=\"kc\">lightblue<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">header<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">background-color<\/span><span class=\"p\">:<\/span> <span class=\"kc\">white<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">max-width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">8<\/span><span class=\"kt\">px<\/span> <span class=\"kc\">auto<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">padding<\/span><span class=\"p\">:<\/span> <span class=\"mi\">8<\/span><span class=\"kt\">px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nt\">article<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"k\">background-color<\/span><span class=\"p\">:<\/span> <span class=\"kc\">white<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">padding<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">width<\/span><span class=\"p\">:<\/span> <span class=\"mf\">8.5<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">11<\/span><span class=\"kt\">in<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"c\">\/* For centering the page on the screen during preparation *\/<\/span>\n    <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">8<\/span><span class=\"kt\">px<\/span> <span class=\"kc\">auto<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">@<\/span><span class=\"k\">media<\/span> <span class=\"nt\">print<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"nt\">html<\/span><span class=\"n\">,<\/span>\n    <span class=\"nt\">body<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">background-color<\/span><span class=\"p\">:<\/span> <span class=\"kc\">white<\/span> <span class=\"cp\">!important<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nt\">body<\/span> <span class=\"o\">&gt;<\/span> <span class=\"nt\">header<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">display<\/span><span class=\"p\">:<\/span> <span class=\"kc\">none<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nt\">article<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"cp\">!important<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">style<\/span><span class=\"p\">&gt;<\/span>\n\n<span class=\"p\">&lt;<\/span><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">header<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Some help text to explain the purpose of this generator.<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span> <span class=\"na\">onclick<\/span><span class=\"o\">=<\/span><span class=\"s\">\"return window.print();\"<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Print<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">header<\/span><span class=\"p\">&gt;<\/span>\n\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">article<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Sample page 1<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"\">sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">article<\/span><span class=\"p\">&gt;<\/span>\n\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">article<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span><span class=\"\">Sample page 2<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"\">sample text<\/span><span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">article<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">&lt;<\/span><span class=\"p\">\/<\/span><span class=\"nt\">html<\/span><span class=\"p\">&gt;<\/span>\n<\/pre>\n<\/div>\n<\/blockquote>\n\n\n\n<!--nextpage-->\n","protected":false},"excerpt":{"rendered":"<p class=\"excerpt\">CSS for printing to paper I do like articles explaining how to use CSS for printing!<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"https:\/\/monodes.com\/predaelli\/2024\/03\/05\/css-for-printing-to-paper\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"federated","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[127,46],"tags":[324],"class_list":["post-11412","post","type-post","status-publish","format-standard","hentry","category-html","category-web","tag-css"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6daft-2Y4","jetpack-related-posts":[{"id":4923,"url":"https:\/\/monodes.com\/predaelli\/2018\/11\/17\/css-the-perfect-print-stylesheet-the-jotform-blog\/","url_meta":{"origin":11412,"position":0},"title":"CSS: The Perfect Print Stylesheet | The JotForm Blog","author":"Paolo Redaelli","date":"2018-11-17","format":false,"excerpt":"Here's something I shall add to my themes, expecially \"bollettino\" and \"qualita\": CSS: The Perfect Print Stylesheet | The JotForm Blog CSS: The Perfect Print Stylesheet by Andreas Hecht Even today, there are still many people that want to print out the entire internet. This can have many reasons. Maybe\u2026","rel":"","context":"In &quot;HTML&quot;","block_context":{"text":"HTML","link":"https:\/\/monodes.com\/predaelli\/category\/html\/"},"img":{"alt_text":"a4-print","src":"https:\/\/i0.wp.com\/www.noupe.com\/wp-content\/uploads\/2014\/06\/a4-print.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.noupe.com\/wp-content\/uploads\/2014\/06\/a4-print.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.noupe.com\/wp-content\/uploads\/2014\/06\/a4-print.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":9530,"url":"https:\/\/monodes.com\/predaelli\/2022\/08\/03\/how-to-create-printer-friendly-pages-with-css\/","url_meta":{"origin":11412,"position":1},"title":"How to Create Printer-friendly Pages with CSS","author":"Paolo Redaelli","date":"2022-08-03","format":"link","excerpt":"How to Create Printer-friendly Pages with CSS How to Create Printer-friendly Pages with CSS CSS Craig BucklerJanuary 5, 2020 Share This article was updated in 2020 to reflect latest best practices in CSS print styling. In this article, we review the art of creating printer-friendly web pages with CSS. \u201cWho\u2026","rel":"","context":"In &quot;Web&quot;","block_context":{"text":"Web","link":"https:\/\/monodes.com\/predaelli\/category\/web\/"},"img":{"alt_text":"Firefox print preview mode","src":"https:\/\/i0.wp.com\/uploads.sitepoint.com\/wp-content\/uploads\/2018\/08\/1577925121printer-friendly-css-05-firefox.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/uploads.sitepoint.com\/wp-content\/uploads\/2018\/08\/1577925121printer-friendly-css-05-firefox.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/uploads.sitepoint.com\/wp-content\/uploads\/2018\/08\/1577925121printer-friendly-css-05-firefox.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":10748,"url":"https:\/\/monodes.com\/predaelli\/2023\/08\/30\/my-little-printer-friendly-css\/","url_meta":{"origin":11412,"position":2},"title":"My little printer-friendly CSS","author":"Paolo Redaelli","date":"2023-08-30","format":false,"excerpt":"Here is my little \"Printer friendly CSS\" that I add to each and every page using Simple Custom CSS and JS \/* override styles when printing *\/ @media print { @page { margin: 2cm; @top-center { font-family: sans-serif; font-weight: bold; font-size: 2em; content: counter(page); } } \/* target the first\u2026","rel":"","context":"In &quot;Tricks&quot;","block_context":{"text":"Tricks","link":"https:\/\/monodes.com\/predaelli\/category\/documentations\/tricks\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5369,"url":"https:\/\/monodes.com\/predaelli\/2019\/03\/19\/8-useful-css-tricks-parallax-images-sticky-footers-and-more\/","url_meta":{"origin":11412,"position":3},"title":"8 useful CSS tricks: Parallax images, sticky footers and more","author":"Paolo Redaelli","date":"2019-03-19","format":"link","excerpt":"8 useful CSS tricks: Parallax images, sticky footers and more This article shares some of my most satisfying \u201cah-hah!\u201d moments learning CSS, and I hope it can prompt some \u201cah-hah!\u201d moments for you too. Sticky Footer Zoom-on-Hover Images Instant Night Mode Custom Bullet Points Parallax Images Animation with Cropped Images\u2026","rel":"","context":"In &quot;HTML&quot;","block_context":{"text":"HTML","link":"https:\/\/monodes.com\/predaelli\/category\/html\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":10190,"url":"https:\/\/monodes.com\/predaelli\/2023\/01\/06\/a-collection-of-popular-layouts-and-patterns-made-with-css-css-layout\/","url_meta":{"origin":11412,"position":4},"title":"A collection of popular layouts and patterns made with CSS &#8211; CSS Layout","author":"Paolo Redaelli","date":"2023-01-06","format":false,"excerpt":"A collection of popular layouts and patterns made with CSS - CSS Layout","rel":"","context":"In &quot;Web&quot;","block_context":{"text":"Web","link":"https:\/\/monodes.com\/predaelli\/category\/web\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":10151,"url":"https:\/\/monodes.com\/predaelli\/2022\/12\/26\/css-infinite-3d-sliders\/","url_meta":{"origin":11412,"position":5},"title":"CSS Infinite 3D Sliders","author":"Paolo Redaelli","date":"2022-12-26","format":false,"excerpt":"CSS Infinite 3D Sliders CSS-Tricks is really a huge treasure","rel":"","context":"In &quot;HTML&quot;","block_context":{"text":"HTML","link":"https:\/\/monodes.com\/predaelli\/category\/html\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/11412","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/comments?post=11412"}],"version-history":[{"count":0,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/11412\/revisions"}],"wp:attachment":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/media?parent=11412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/categories?post=11412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/tags?post=11412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}