Now Reading
CSS for printing to paper

CSS for printing to paper

2024-03-03 15:22:23

Back to writing

    Desk of contents

  1. Introduction
  2. Sample files
  3. @page
  4. @media print
  5. Width, height, margin, and padding
  6. Element positioning
  7. Multi-page documents with repeating elements
  8. Portrait / Landscape mode
  9. Data source
  10. Essentials cheatsheet

Introduction

At work, one of many issues I do fairly usually is write print turbines in HTML to recreate and substitute types that the corporate has historically executed handwritten on paper or in Excel. This permits the corporate to maneuver into new web-based instruments the place the shape is autofilled by URL parameters from our database, whereas getting the identical bodily output everybody’s accustomed to.

This text explains among the CSS fundamentals that management how your webpages look when printed, and a few suggestions and tips I’ve realized which may provide help to out.

Pattern information

Listed below are some pattern web page turbines to ascertain some context, and maybe a shred of credibility.

I will be the primary to confess these pages are a little bit bit ugly and will use extra polish. However they get the job executed and I am nonetheless employed.

Invoice generator

Coversheet with sidebar inputs

Coversheet with contenteditable

QR code generator

@web page

CSS has a rule referred to as @page that informs the browser of your web site’s printing preferences. Usually, I exploit

@web page
{
    measurement: Letter portrait;
    margin: 0;
}

I’ll clarify why I select margin: 0 within the later part about margins. It’s best to use Letter or A4 as acceptable in your relationship with the metric system.

Setting the scale and margin of @web page just isn’t the identical as setting the width, peak, and margin of your <html> or <physique> aspect. @web page is past the DOM — it comprises the DOM. On the net, your <html> aspect is bounded by the perimeters of your display screen, however when printing it’s bounded by @web page.

The settings managed by @web page roughly correspond to the settings you get in your browser’s print dialog whenever you press Ctrl+P.

Here is a pattern file I used to do some experiments:

<!DOCTYPE html>
<html>
<fashion>
@web page
{
    /* see under for every experiment */
}
html
{
    width: 100%;
    peak: 100%;
    background-color: lightblue;

    /* grid by shunryu111 https://stackoverflow.com/a/32861765/5430534 */
    background-size: 0.25in 0.25in;
    background-image:
    linear-gradient(to proper, grey 1px, clear 1px),
    linear-gradient(to backside, grey 1px, clear 1px);
}
</fashion>
<physique>
    <h1>Pattern textual content</h1>
    <p>pattern textual content</p>
</physique>
</html>

Here is how that appears within the browser:

And listed here are the outcomes of some completely different @web page values:

@web page { measurement: Letter portrait; margin: 1in; }:

@web page { measurement: Letter panorama; margin: 1in; }:

@web page { measurement: Letter panorama; margin: 0; }:

Setting the @web page measurement will not truly put that measurement of paper into your printer’s feed tray. You’ll have to do that part yourself.

Discover how once I set measurement to A5, my printer stays on Letter, and the A5 measurement matches totally inside the Letter measurement which provides the looks of a margin despite the fact that it is not coming from the margin setting.

@web page { measurement: A5 portrait; margin: 0; }:

But when I inform the printer that I’ve precise A5 paper loaded, then it seems to be as anticipated.

From what I collect by experimentation, Chrome solely follows the @web page rule you probably have Margin set to Default. As quickly as you modify Margin within the print dialog, your output is as a substitute the product of your bodily paper measurement and the chosen margin.

@web page { measurement: A5 portrait; margin: 0; }:

Even whenever you select a @web page measurement that matches absolutely inside your bodily paper, the margin nonetheless issues. Right here, I make a 5×5 sq. with no margin, and a 5×5 sq. with margin. The scale of the <html> aspect is bounded by the @web page measurement and margin mixed.

@web page { measurement: 5in 5in; margin: 0; }:

@web page { measurement: 5in 5in; margin: 1in; }:

I did all these exams not as a result of I count on to print on A5 or 5×5 paper, however as a result of it took me some time to determine what precisely @web page is. Now I’m fairly assured in at all times utilizing Letter with margin 0.

There’s a media query referred to as print the place you may write kinds that solely apply throughout printing. My generator pages usually include a header, some choices, and a few assist textual content for the consumer that clearly should not come out on the print, so that is the place you add show:none on these parts.

/* Regular kinds that seem if you are making ready the doc */
header
{
    show: block;
}

@media print
{
    /* Disappear if you end up printing the doc */
    header
    {
        show: none;
    }
}

Width, peak, margin, and padding

You will have to know a bit in regards to the box model to get the margins you need with out wrestling the pc an excessive amount of.

The explanation I at all times set @web page margin: 0 is that I might quite deal with the margins on the DOM parts as a substitute. After I tried to make use of @web page margin: 0.5in, I’d usually by accident wind up with double-margins that squash the content material smaller than I anticipated, and my one-page design spilled onto a second web page.

If I wished to make use of @web page margin, then the precise web page content material would should be laid out all the way in which up towards the perimeters of the DOM, which is tougher for me to consider and tougher to preview earlier than printing. It’s mentally simpler for me to do not forget that <html> occupies your entire bodily paper and my margins are inside the DOM as a substitute of past it.

@web page
{
    measurement: Letter portrait;
    margin: 0;
}
html,
physique
{
    width: 8.5in;
    peak: 11in;
}

In the case of multi-page print turbines, you are going to need a separate DOM aspect representing every web page. Since you may’t have a number of <html> or <physique>, you are going to want one other aspect. I like <article>. Even for single-page turbines, chances are you’ll as nicely at all times use an article.

Since every <article> represents one web page, I do not need any margins or padding on <html> or <physique>. We’re pushing the logic one step additional — it’s simpler for me to let the article occupy your entire bodily web page and put my margins inside it.

See Also

@web page
{
    measurement: Letter portrait;
    margin: 0;
}
html,
physique
{
    margin: 0;
}

article
{
    width: 8.5in;
    peak: 11in;
}

After I speak about including margin inside my article, I am not utilizing the margin property, I am utilizing padding. That is as a result of margin goes exterior and round your aspect within the field mannequin. For those who use a margin of 0.5in, you will should set the article to 7.5×10 in order that the article plus 2×margin equals 8.5×11. And if you wish to modify that margin you will have to regulate the opposite dimensions.

As a substitute, padding goes on the within of the aspect, so I can outline the article to be 8.5×11 with 0.5in padding, and all the weather contained in the article will keep on the web page.

A whole lot of instinct about aspect dimensions is simpler whenever you set box-sizing: border-box. It makes it in order that the outer dimensions of the article are locked in when you modify the internal padding. That is my snippet:

html
{
    box-sizing: border-box;
}
*, *:earlier than, *:after
{
    box-sizing: inherit;
}

Let’s put this all collectively:

@web page
{
    measurement: Letter portrait;
    margin: 0;
}

html
{
    box-sizing: border-box;
}
*, *:earlier than, *:after
{
    box-sizing: inherit;
}

html,
physique
{
    margin: 0;
}

article
{
    width: 8.5in;
    peak: 11in;
    padding: 0.5in;
}

Aspect positioning

As soon as you have bought your articles and margins arrange, the area contained in the article is yours to do with as you please. Design your doc utilizing no matter HTML/CSS you’re feeling is suitable for the undertaking. Generally this implies laying out parts with flex or grid since you’ve been given some leeway with the output. Generally it means creating squares of a particular measurement to suit on a sure model of sticker paper. Generally it means completely positioning completely all the pieces to the millimeter as a result of the consumer must feed a particular piece of pre-labeled paper by the printer to get your information on high of it, and you are not answerable for that particular paper.

I am not right here to present a tutorial on learn how to write HTML generally, so you will want to have the ability to do this. All I can say is be conscious of that reality that you just’re coping with the restricted actual property of a bit of paper, in contrast to a browser window which might scroll and zoom to any size or scale. In case your doc will include an arbitrary variety of objects, be able to paginate by creating extra <article>.

Multi-page paperwork with repeating parts

A whole lot of the print turbines I write include tabular information, like an bill stuffed with line objects. In case your <desk> is giant sufficient to go onto a second web page, the browser will robotically duplicate the <thead> on the high of every web page.

<desk>
    <thead>
        <tr>
            <th>Pattern textual content</th>
            <th>Pattern textual content</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>0</td><td>0</td></tr>
        <tr><td>1</td><td>1</td></tr>
        <tr><td>2</td><td>4</td></tr>
        ...
    </tbody>
</desk>

That is nice in the event you’re simply printing a <desk> with no frills, however in a number of actual eventualities it is not that straightforward. The doc I am recreating usually has a letterhead on the highest of every web page, a footer on the underside, and different customized parts that should be explicitly repeated on every web page. For those who simply print a single lengthy desk throughout pages, you do not have a lot means to put different parts above, under, and round it on intermediate pages.

So, I generate the pages utilizing javascript, splitting the desk into a number of smaller ones. The final method right here is that this:

  1. Deal with the <article> parts as disposable and be able to regenerate them at any time from objects in reminiscence. All consumer enter and configuration ought to happen in a separate header / choices field, exterior of the articles.
  2. Write a operate referred to as new_page that creates a brand new article aspect with the required repeating header/footer/and so on.
  3. Write a operate referred to as render_pages that creates the articles from the bottom information, calling new_page each time it fills up the earlier one. I often use offsetTop to see when the content material is getting far alongside the web page, although you can positively use smarter strategies to get the right match on every web page.
  4. Name render_pages each time the bottom information adjustments.
operate delete_articles()
{
    for (const article of Array.from(doc.getElementsByTagName("article")))
    {
        doc.physique.removeChild(article);
    }
}

operate new_page()
{
    const article = doc.createElement("article");
    article.innerHTML = `
    <header>...</header>
    <desk>...</desk>
    <footer>...</footer>
    `;
    doc.physique.append(article);
    return article;
}

operate render_pages()
{
    delete_articles();

    let web page = new_page();
    let tbody = web page.question("desk tbody");
    for (const line_item of line_items)
    {
        // I often decide this threshold by experimentation however you may in all probability
        // do one thing extra rigorously right.
        if (tbody.offsetTop + tbody.offsetParent.offsetTop > 900)
        {
            web page = new_page();
            tbody = web page.question("desk tbody");
        }
        const tr = doc.createElement("tr");
        tbody.append(tr);
        // ...
    }
}

It’s often good to incorporate a “web page X of Y” counter in your pages. For the reason that variety of pages just isn’t identified till all pages are generated, I can not do that throughout the for loop. I name a operate like this on the finish:

operate renumber_pages()
{
    let pagenumber = 1;
    const pages = doc.getElementsByTagName("article");
    for (const web page of pages)
    {
        web page.querySelector(".pagenumber").innerText = pagenumber;
        web page.querySelector(".totalpages").innerText = pages.size;
        pagenumber += 1;
    }
}

Portrait / Panorama mode

I’ve proven that the @web page rule helps inform the browser’s default print settings, however the consumer can override it in the event that they need to. For those who set @web page to portrait mode and the consumer overrides it to panorama mode, your format and pagination may look unsuitable, particularly if you’re hardcoding any web page thresholds.

You may accommodate them by creating separate <fashion> parts for portrait and panorama, and utilizing javascript to modify between them. There is perhaps a greater approach to do that, however at-rules like @web page behave in a different way than regular CSS properties so I am undecided. You must also avoid wasting variable that may assist your render_pages operate do the suitable factor.

You may additionally cease hardcoding thresholds, however then I might should comply with my very own recommendation.

<choose onchange="return page_orientation_onchange(occasion);">
    <choice chosen>Portrait</choice>
    <choice>Panorama</choice>
</choose>
<fashion id="style_portrait" media="all">
@web page
{
    measurement: Letter portrait;
    margin: 0;
}
article
{
    width: 8.5in;
    peak: 11in;
}
</fashion>

<fashion id="style_landscape" media="not all">
@web page
{
    measurement: Letter panorama;
    margin: 0;
}
article
{
    width: 11in;
    peak: 8.5in;
}
</fashion>
let print_orientation = "portrait";

operate page_orientation_onchange(occasion)
{
    print_orientation = occasion.goal.worth.toLocaleLowerCase();
    if (print_orientation == "portrait")
    {
        doc.getElementById("style_portrait").setAttribute("media", "all");
        doc.getElementById("style_landscape").setAttribute("media", "not all");
    }
    if (print_orientation == "panorama")
    {
        doc.getElementById("style_landscape").setAttribute("media", "all");
        doc.getElementById("style_portrait").setAttribute("media", "not all");
    }
    render_printpages();
}

operate render_printpages()
{
    if (print_orientation == "portrait")
    {
        // ...
    }
    else
    {
        // ...
    }
}

Knowledge supply

There are a few methods to get your information onto the web page. Generally, I pack the entire information into the URL parameters, so the javascript simply does const url_params = new URLSearchParams(window.location.search); after which a bunch of url_params.get("title"). This has some benefits:

  • The web page masses very quick.
  • It is easy to debug and experiment by altering the URL.
  • The generator works offline.

This additionally has some disadvantages:

  • The URLs turn out to be very lengthy and unweildy, folks can not comfortably e-mail them to one another. See pattern hyperlinks on the high of this text.
  • If the URL does get despatched in an e-mail, that information is “locked in”, even when the supply document in your database adjustments later.
  • Browsers do have limits on URL size. The boundaries are fairly excessive however not infinite and may fluctuate per consumer.

Generally I as a substitute use javascript to fetch our database data over the API, so the URL parameters simply include the document’s major key and perhaps a mode setting.

This has some benefits:

  • The URLs are a lot shorter.
  • The info is at all times recent.

and downsides:

  • The consumer has to attend a second whereas the information is being fetched.
  • It’s a must to write extra code.

Generally I set contenteditable on the articles so the consumer could make small adjustments earlier than printing. I additionally like to make use of actual, reside checkbox inputs they will click on earlier than printing. These options add some comfort, however normally it could be wiser to make the consumer change the supply document within the database first. Additionally, they restrict your means to deal with the article parts as disposable.

Necessities cheatsheet

sample_cheatsheet.html

<!DOCTYPE html>
<html>
<fashion>
@web page
{
    measurement: Letter portrait;
    margin: 0;
}
html
{
    box-sizing: border-box;
}
*, *:earlier than, *:after
{
    box-sizing: inherit;
}

html,
physique
{
    margin: 0;
    background-color: lightblue;
}

header
{
    background-color: white;
    max-width: 8.5in;
    margin: 8px auto;
    padding: 8px;
}

article
{
    background-color: white;
    padding: 0.5in;
    width: 8.5in;
    peak: 11in;

    /* For centering the web page on the display screen throughout preparation */
    margin: 8px auto;
}

@media print
{
    html,
    physique
    {
        background-color: white !essential;
    }
    physique > header
    {
        show: none;
    }
    article
    {
        margin: 0 !essential;
    }
}
</fashion>

<physique>
    <header>
        <p>Some assist textual content to elucidate the aim of this generator.</p>
        <p><button onclick="return window.print();">Print</button></p>
    </header>

    <article>
        <h1>Pattern web page 1</h1>
        <p>pattern textual content</p>
    </article>

    <article>
        <h1>Pattern web page 2</h1>
        <p>pattern textual content</p>
    </article>
</physique>
</html>

View this document’s history

Contact me: writing@voussoir.internet

If you want to subscribe for extra, add this to your RSS reader: https://voussoir.net/writing/writing.atom

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top