“Polyfill is the greek word for hack” — Dave Cramer
A polyfill is a bit of code used to simulate features in a browser that doesn’t support them yet. For a while, using svg in the browser was made using the svgweb.js
library, able to convert those code into shapes on screen. And then, browsers evolved and once they managed to support svg without help, svgweb
wasn’t really useful anymore.
Paged.js is a polyfill for all the features for print that folks have been pushing to the W3C. With a slight distinction, since the printing module of the browsers are not really available through javascript as browsers use other dependencies to print paper or generate PDF. And since we can’t really do anything to that PDF generator, Paged.js is cheating a little bit by faking the result of the printing process on the screen: we can preview the page, its margins, by recreating the html and css that will be rendered on screen and then we can print this whole preview.
We’re simulating print on screen, and by doing so, we’re blurring a little bit the distinction between the print and screen medias of the css, since we’re translating print for the screen. And this gives us superpowers, simply by giving acces to the inspector, to explore the source code of our printed page. And we can do a lot to those pages before printing them, as we’d design a website, using css and javascript, and we can also transform the content as it’s being deployed on the page: for example, you can calculate the size of an image and automatically decide if there is enough room on the page, or if you want to move it to the next and keep the rest of the text flowing.
Possibilities are endless, and you can do a pretty good automated layout, and yet you can still have a typesetter or a designer clean up everything.
This hack polyfill has become the main feature of Paged.js: web designer could start to work on printed stuff without having to leave the tool they know and love, graphic desginers who were used to wysiwyg got a place to try webdesign tools in the most tangible way, using a finished canvas instead of this infinite screen, and industries could use web2print and single source publishing ideas and keep the workers to make sure the quality is still there.
This is the work of the polyfill: prove that something works by offering the features and find users to promote them, and then disappear as the browsers took over the work. And then Chromium, starting from version 131, supports the margin-boxes
allowing users to add content in the margins of a printed media, without the need of showing them on screen. This signal that things finally get to move in the CSSPrint world is amazing, and we’be been waiting for decades (literally), which forces us to ask ourselves: what shall we do with Paged.js and how should we move around this evolution. Right now, there is no plan to quit Paged.js: browsers only support a tiny tiny bit of what Paged.js support, and when i say browser, it’s only really chromium and blink-based browsers. But we need to take into account those changes, and find the right spot to stand on to make sure that what we want to be able to do for print with web technologies get in.
For now, you can still use Paged.js as you would normally, there may be some bugs here and there, but nothing you can’t override with hooks or Paged.js fixes. That said, as the browsers ship features for print, Paged.js will need to evolve to either support them, or support the browser implementation. Let’s take a look at a simple example: let’s say we have a table of content, and that Chrome supports target-counter
(which is not yet the case but let’s assume it will at some point). So Paged.js will find this target-counter
and convert it to what it needs to be, and then Chrome will do the exact same thing, and the table of content will show the same page number twice, which is definitely what we don’t want to happen. So which one should we use and in which cases?
Until we spend enough time of work that, Gijs, Fred and myself will be working on figuring it out. And to do so, we made the decision of modularizing Paged.js into smaller dependencies that we’ll be able to update as time goes by, making sure that we could replace some bits wihtout having to throw everything away everytime a new feature appears.
Let’s get practical
Paged.js works on 3 pillars, that are a bit complex to define, because they’re too much intertwined, but let’s try it anyway.
- the
chunker
is the module in charge of placing elements on the page, find the overflow, mark the spot of the break, add a new page, and keep doing it. The paper cutter for the web. - the
polisher
is in charge of locating the stylesheets, and styles and mark the content that will need some custom transformation for print: avoiding page break, changing colors when on a new page. It reads the CSS, transform the HTML, before pages are generated - the
previewer
is the main orchestrator of this whole little world, managing all the little tasks that all the other modules run.
Those three bits will change. Some will be quite transformed, others will be a tiny bit changed and we’ll be quite precautionous to make sure that, if someone followed the W3C specs for print, then they’ll be able to keep using their code without any changes. If you did have some specific custom hooks, some things may change a bit, but we’ll explain those as we go.
First change: the chunker
will soon be its own javascript library. It will be able to take a content, fill an HTML element
with it, and return the overflowing bit and the multiple break tokens. Paged.js will use that library as a dependency, and it will help us quite a lot to test new HTML elements and new CSS features without having to run Paged.js. The second interesting bit of that is that we’ll be able to run multiple chunkers in multiple places, allowing for very complex layout with multiple flows or customs side/margin notes, or, in another context, it will allow for chained block, like you would have in a classic book designing program. We also want to change how the overflow is found in today’s Paged.js and instead of stoping as soon as something overflow, we want to let the browser do its job and find the overflow after, using the Interesection Observer API
Second change, the creations of a set of web-component
for print that Paged.js will use instead of the template literals we have today. <paged-page>
will generate a page on screen ready to be printed. This component will come with their own CSS and javascript for print and will ease some of the work we do for customizing pages (to allow for PDF with different page sizes and orientation). These components will be usable without Paged.js and will simplify any project that would need a preview on screen for printed matters.
Third change, we’re replacing CSS Tree
with CSS OM
. The idea is to avoid the preprocessing of any CSS. This will give us more control on what CSS we’ll polyfill. This will give us more stability over time, and reduce dependencies as much as possible.
There are a bunch of other changes in the pipes, including some update on the website (which is almost completely updated as you can now participate in its translations to any language you’d like). a rewriting of all the documentation that will include a real developer docs for contributors and a better css print 101., from the long awaited dev documentation for the development of the library and an update of the user manual (more like a CSS print course), and we’re now thinking of who should take part in the governance of Paged.js future.
There a lot on the plates.