CSS for printing to paper
voussoir.net
voussoir.net
h2,h3,h4,h5,h6,h7,h8 {break-after: avoid-page;}
img, svg, table, canvas {break-inside: avoid;}
a::after {content: " (" attr(href) ")";}
Explanation:- Avoid printing section headers at the bottom of one page with the section content left headerless at the top of the next page.
- Prefer printing graphics and figures on whole pages instead of split across pages.
- Print out the URL of every hyperlink instead of having links only as useless underlined text.
I don't think that h7 and h8 exist?! Are you sure this is necessary? And why no h1?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/He...
No h1 because there is only ever one of those and it's at the top of the first page.
Like if I've got
<a href="https://www.google.com/">https://www.google.com/</a>
Will it print like this? https://www.google.com (https://www.google.com)For many years now, and alongside my "regular" CV, I've had a Markdown to PDF script that uses @page and @media in a small HTML template and essentially creates custom 1-pagers in US format. Instant recruiter turnaround.
In between this and the OP's table splitting trick, this was a good 15m spent on HN.
I have used, too:
footer {
page-break-inside: avoid;
}
summary {
page-break-after: avoid;
}
body {
min-width: 992px;
}
Explanation:- I usually don't want to break the page footer.
- Similar to headings, usually it is not desirable to produce a break after the summary element (for details element). If the details elements are never longer than the page, `details {break-inside: avoid;}`can be useful.
- Avoids rendering the mobile version of a page
The real power is in being able to hook up all the templating, CMS APIs, and whatever else you want into your content pipeline. It’s Just HyperText™.
I’d go so far to say that if you’re equally comfortable in HTML/CSS and InDesign, Pagedjs is a superior choice for long form layout.
CSS is very compelling, but then based on my personal experience as print media designer the likes of InDesign are full of various special tricks (and language-specific, too) for alleviating white space corridors, handling hanging punctuation, hyphenation, etc. that the enterprise-level software tends to accumulate (due to the business model if nothing else).
I’ve just set up our publications to use PagedJS, and with a fair amount of hacking I was able to set up a baseline grid. Hyphenation depends on the browser implementation, which is OK for English in recent Chromium. The new text-wrap property has also been helpful. Hanging punctuation is only supported in Safari if I remember correctly.
But being able to produce nice looking PDFs from a markdown document, with automated endnotes and table of contents, is a much nicer process than going through InDesign, and I also say this as someone equally comfortable with both. And the result is good enough for our purposes.
Here is an example: https://www.lowyinstitute.org/sites/default/files/2024-03/LA...
Now I’m not using ID much, and struggling with generating PDFs from HTML, so I really appreciated the example you gave. Great work!
I concur on the warm fuzzy blanket of DTP software, personally.
this type of description of using CSS for DTP reminds me of using tables for layout before CSS. it was a bullshit solution waiting for something better. only, in this case, DTP software is already there and better. so why would someone do this to themselves?
That seems to concur with an informative article by AtaDistance from 2019 that I read the other day [0]:
> ...
> The result was InDesign 1.0 J which shipped in early 2001. InDesign J was the first, and only, major software application developed outside of Japan that followed the Japanese Industrial Standard (JIS) X4051 typesetting and composition specification (the kumihan “bible”) and traditional Japanese print production methods.
> I have covered some basics of Japanese layout before, but a review is helpful for first time readers. I’ll use a mix of my material and McCully’s presentation to explain.
> ...
> Western created DTP layout is graphics-driven and calculated by margins and font baselines. The western baseline typography model and font metrics is how PostScript and OpenType fonts, and all layout engines evolved. Adobe was well acquainted with the shortcomings of their own font technology and InDesign J got around the problems by adding proprietary Kanji virtual body font metrics and Japanese line break algorithms. None of this exists as an open standard that benefits everybody.
> That is fine for InDesign and print production, but web layout and typography via CSS is an entirely different world. There are 3 huge obstacles for good vertical Japanese typography on the web:
> * No font metrics for virtual body/em-box glyph space placement: everything has to be accomplished with baseline metrics
> * No reliable space control
> * No reliable line breaks
[0] https://atadistance.net/2019/04/26/the-state-of-css-japanese...
[1] https://github.com/ggrossetie/asciidoctor-web-pdf
[2] Asciidoc has four major PDF pipelines in some form of maintenance. The vanilla, asciidoctor-pdf, is a Ruby-based Prawn PDF generator, and it's good but limited in terms of layout - you end up having to extend the core Asciidoctor processor for a lot of tricks like LoT/LoF. Asciidoctor-pdf, and I really want to emphasize this, is the official PDF pipeline for adoc files. The older pipeline, FOPUB, is based on DocBook, which Asciidoc has equivalency with. But DocBook means XSL, and XSL means cheating on Russian roulette because just one out of six chance of ENDING THE PAIN is not enough. The odd man out is DBLATEX, which goes Asciidoc->DocBook->LaTeX-> PDF, and . . whew, ok man, you're jumping three markup languages, dude. Other than that, LaTeX is pretty much the gold standard for layout markup. Finally, we got this thing, asciidoctor-web-pdf, which honestly is more or less dead in terms of activity, which sucks. Web-pdf gives me the flexibility of DocBook-XSL (and then some!) but with CSS and, if I need it, JS. Unfortunately, LoT/LoF still needs Asciidoctor extensions . . but you get a lot of toys that aren't possible with asciidoctor-pdf/prawn.
[3] Shared by vivliostyle and a few others.
Open-access textbook: https://www.utilitarianism.net/
Open source: https://github.com/whyboris/utilitarianism.net
Is there any easy to use/hack HTML layouting engine where I could experiment with custom CSS attributes and bridge that gap? Would anything from Servo be suitable?
Modifying an entire browser with its bloat is too much effort. There is no JS or cookies on paper (they can be in paper if you wrap them).
Servo could be used for this. You'd want to add support for parsing the CSS properties themselves to the style crate in https://github.com/servo/stylo and then the layout implementation to the layout2020 crate in https://github.com/servo/servo. You do effectively get a whole browser though.
I'm currently working on building a lighter weight / hackable layout engine based on a combination of https://github.com/servo/stylo (for css parsing and selector resolution), https://github.com/DioxusLabs/taffy (for box-level layout) and https://github.com/pop-os/cosmic-text (for flow/inline layout). I expect to have something decent in around 6 months
Neither of these setups currently have any support for pagination though.
[0]: https://weasyprint.org/ [1]: https://www.princexml.com/
Now, ok, funny thing. Engineering could just get bare metal laptops, whenever they wanted, then blow the thrice-blessed CentOS image on it, and then do whatever the hell. So what happened - and this probably sounds real predictable - they used the CentOS machines to make all sorts of nutty crap, boxed it up, and then sent it back to their "official" Windows machines, now as a locked-in-amber config that never updates, even if five years later it had like fifty zero days in it and none of the libraries were good anymore.
I understand it took a new director and a LOT of meetings to explain whitelist mirrors for package managers, but I was long gone by then, even if I had a tiny hand in rolling out the demo whitelist mirror on-prem. Man, I had no idea what I was doing . . it still makes me shudder when I think of the things they were asking me to do.
Firefox forgot to render images after a few pages. So on some labels the barcodes were not printed.
Chrome looked good at the fist glance. But it turned out that the plot/cut lines (which I created via CSS borders) had been shifted by 1-2mm on _some_ pages. Result was garbage.
I finally switched to https://github.com/flyingsaucerproject/flyingsaucer which is a high quality HTML/CSS to PDF library. Only drawback is that it only supports CSS 2.1, so some fancy features are not supported like rotating text.
No issues with image rendering in firefox.
It works now, but first you have to download a PDF and print that. Google Docs does this too when you hit "Print".
I've tried hacks like load the PDF in an iframe and use some JavaScript to print that, but then I get footers with the URL of the webpage, which doesn't work for my purposes.
If you work on Chrome/Blink, Safari/Webkit, or Firefox/Mozilla please please please at least get the hacks working!
A CSS standard would be great, but really I'd be happy if I could call a function like `windows.print("/document.pdf")` and have it print the PDF without all the footer/headers stuff.
Not if you need to support a bunch of different printers.
For me PDF is the way to go, but browsers can't print a PDF via a "Print" button within the HTML, so instead I have to build apps that download the PDF and print it directly through operating system APIs.
- have a print.html template page
- use iframe to render and load the page
- either on the print page, or from top frame, call window.print
You can use the aforementioned js libraries to generate footers and such, and use any print css. You can test the print layout in your dev tools, no need to wait for browser preview.
Note that browsers will try to render thead and tfooter elements on every page their parent table spans, that can be very useful.
At work we have a playwright container with express js waiting for incoming requests to load the print.html page and save it as pdf. We're also using volumes so that all data exchange happens in disk and not being passed around in http requests.
PDFs that took maybe 30 seconds with weasy print, now take 5 seconds.
You will need adobe acrobat (free). This is a very old trick but still works on Windows 10. We use it with the latest edge.
I do wish that the browser had a special direct printing option.
https://groups.google.com/g/comp.text.pdf/c/dHuBMsaovco?pli=...
I would like to have a thermal printer that plugs into the computer via USB and appears as a mass storage device. When you drop an image file (PNG, BMP) into it, it prints it out. A config file would tell the printer what paper stock you have loaded. This way the computer does not need any special drivers, and it would be so stupidly easy to write programs that generate image files to be printed. I think more hardware should take advantage of filesystem operations as a control method.
If someday you ever think about producing a first-party thingybase printer...
CSS started with print media in mind since this was what was available at the time.
Many of these features have been there since the inception. Just that browser support has been lagging.
How do you break a table inside a float? Etc.
I originally was going to generate PDFs, but my backend is in python, and all the PDF generators have some issues with SVG images, especially with gradients. The site is a wiki, so SVG seemed like the best way to map courses while allowing them to easily be edited down the road. Since CSS and SVG work hand in hand, I decided to start working on that, and it's actually turned out okay.
If you want to see it in action, you can pop over and look at any of the courses marked with a blue or red flag on the homepage, but a very good example is Pasatiempo, here: https://golfcourse.wiki/print_options/course/pasatiempo_golf...
The certificate templates are HTML files, and I use https://github.com/cognitom/paper-css to make them print-friendly.
Before that i made a online editor to create certificates for workshops and courses, again used the same technique.
Both projects are kinda dead now, but it was nice getting everything done using only vanilla JS and CSS. Very powerful stuff.
After a bit of tinkering, I was able to print 6.2x12.4cm labels with a QR code. Really fun to watch it spit out these stickers. Each sticker has a unique QR code with the printed code in text form below it.
Some gotchas:
- you have to use margin 0 to hide the ugly browser headers that get added in the margin otherwise.
- Firefox has no print preview. This makes testing a bit hard. I used Chrome for testing this in the end.
- To print, you replace the dom tree with your print page, invoke print, and then copy back the app's root node from javascript. This is ugly as it shows the print page below your print dialog while that is open. I've not found a better way to do this. I guess I can do some non page layout that shows while that happens. Hacky but it works.
- I've yet to make this work in landscape mode where the page is vertical 62x31 layout to print small stickers.
@page {
margin: 0mm;
size: 124mm 62mm;
size: portrait;
.sticker {
padding: 4mm;
page-break-after: always;
}
}
The rest is just usual html layout. I used a simple flex row with two elements. Print quality is surprisingly good. Cost per sticker is around 0.3 cents per sticker. Amazing value.That seems surprising, considering how no-muss no-fuss their hardware & cartridges are. (As compared to, say, H-P.)
File -> Print (ctrl+p), the preview takes up the majority of the dialog.
Table of contents, reflowing content across pages, templated footer, randomly selected background elements on pages.
This let's the Ctrl-P version locally match up with a headless Chromium render, allowing for much easier testing.
It's very flexible to make changes. Not huge files like Photoshop or indesign.
Printing to PDF gets you vector output. Just last week, I built a print ad for a local visitor bureau placement.
Pretty much anything I need for a high-quality print job, I use html/css.
By reading this sentence, you hereby agree to all terms and conditions
presented by voussoir.net, including but not limited to terms which entitle
voussoir.net to a fraction not less than forty (40) percent (%) of your
monthly income from now until an as-yet undetermined time not less than
thirty six (36) months from the present date.[0] https://voussoir.net/writing/css_for_printing/#media_print
[1] https://en.wikipedia.org/wiki/AACS_encryption_key_controvers...
https://www.wearedevelopers.com/en/videos/172/how-to-write-a...
(no need to log in, just inspect the login overlay and remove it and the video will play)
I don’t want someone to tell me what paper I should use (size: Letter portrait). Frankly I don’t own letter-sized paper.
Also all sizes are in inches, which I don’t calculate in and wouldn’t know whether still sensible margins when printing on a different paper size.
That's pretty clearly stated near the top of the article. As a European, if I wrote a similar post I would do it all in metric and trust that my US readers were smart enough to substitute the units of their choice without whining about it. The concepts would not change, and a quick google would tell you that an inch is approx 25mm, which is enough for you to understand what's going on.
If you want to use these techniques on a global site, I think you could use multiple @page styles and switch between them with a dropdown like I did with portrait/landscape. Although A4 and letter are very close in size.
It may not be a lot of CSS, but it is much easier for me to just include the page and have it deal with my page size than to review articles like this when I want to print.
Edit: when I linked to the repo, my comment disappeared. You can find Paper-CSS by searching Github or Node for cognitom/paper-css.
Would love a more experienced HN'ers tip to how to use links in comments w/o causing the comments to disappear.
Then I tell it not to break sections and articles unnecessarily , and let the browser figure it out .
Not a fan of embedding specific sizes into the CSS, I often(Well, not really often as I'm only printing a few times a year) like to print A5.
A4 makes it annoying to try to hold a binder in one hand and takes more space than it really needs to.
These generator pages already rely on javascript to put our database data onto the page, whether by URL parameters or API calls, so once I'm in that mode, yeah I'm generating everything with article.innerHTML = '...' to get a bulk template on the page, and a series of createElement/append to make smaller elements like table rows.
I also made this sample file that shows thead repeating, but since it's a single continuous table it doesn't preview very well and spills out of the 8.5x11 article element. I'm not sure how I would take advantage of the browser's automatic thead/tfoot repeat while also accurately previewing the result in the browser, especially with more elements below the table.
https://voussoir.net/writing/css_for_printing/sample_longtab...
But I'm open to suggestions that would spare me from splitting the table after a height threshold!
@media print {
@page {
@bottom-center { content: counter(page) }
}
works with https://pagedjs.orghttps://developer.mozilla.org/en-US/docs/Web/CSS/@page#brows...
That said, I've always used paged.js with its polyfills to fill in other gaps. So maybe there's something I'm unaware of.
Why do you call paged.js a "hack"?
I'm a big fan of paged.js.
We're working closely with early adopters at this stage.
RIP Format Dynamics.
Let's kill pdf!
It’s like digital, printed paper. Part of the reason is pretty much ubiquitous compatibility.
If it needs to be edited, just don’t print it on digital paper. Does the format have other issues?
1. Dividing some amount of text into pages on a computer screen is unnecessary and annoying.
2. Adobe has a stranglehold on the format and is constantly dicking around with it. Lately I encountered a fillable PDF that Acrobat Reader refused to fill. I could fill it with Firefox but after saving it was no longer a fillable form for any Acrobat user. What's the point of a fillable form that disallows filling it out?!
3. Adobe increasingly supports JavaScript for form validation, etc. I can only imagine what a nightmare mess that is. If we're going to shoehorn in a browser, might as well just use a browser.