clone your own copy | download snapshot


HTML 2 print

This little tool is a boilerplate, a minimal example to start a print project using HTML, less/CSS and Javascript/Jquery to design it.

Why use html to make printed matters?

The most exciting reason to use HTML/CSS is the fact that you can go back and forth between code and visual manipulation thanks to the element inspector of browsers. With Javascript on top of it, you can access every object in the DOM and its properties or do programmatic manipulations. This back-and-forth between hand and code manipulations is new to print production.

The second strong reason why we set this up is that because the design is made with code/text, it means we can use collaborative text editors such as Etherpad to design with several people at the same time.

Why use this instead of libraries such as the PHP library tcpdf which transforms html to a PDF for print?

Because CSS specifications for print are all settled, we are just waiting for browsers vendors to implement them well. Meanwhile, it's already possible to send to an offset printer a file generated from a webpage. So why use a third party engine if you want to print HTML?


  • Crop marks made with CSS gradients
  • Pagination in pure CSS
  • Mixing flowable content and absolute positioned content
  • Image fitting in frame
  • View as spread, and possibly as flatplan, and possibly building imposition plans
  • Preflight packages is built-in: use the "Save Complete Webpage" function of your browser

First launch

Local micro-server

You can't use less.js on a local file (URL starting with "file:///"). To bypass this limitation, you can run a simple webserver with python. To do so, open the file start and go to http://localhost:8000/ with a compatible web browser (see in section Print of the README).


Example is based on an A5 format. Edit: - /content.html: To put your own HTML content; - /setup/setup.js: To change the number of pages and the content file (if different from content.html); - /setup/setup.less: To change the format, margins, header or footer content; - /setup/styles.less: To add your own styles.


To make a PDF, print the page within the browser, and choose «Print to file». Important: choose the right page format (only Chromium's print preview can take the format specified by the CSS). In order to know your paper format (with the crop marks), inspect one ".paper" element with you web inspector, and look at its dimensions in mm. Be sure to remove all margins when creating the custom format!

Tested browsers: - Arora 0.11.0 - Midori - Epiphany 3.16 (3.6.1 doesn't work) - Safari > 7.0 - Chromium from versions 29 to 33 - With polyfill (loaded automatically on Chrome): - Chromium 43 - Firefox 39



«Less is a CSS pre-processor, meaning that it extends the CSS language, adding features that allow variables, mixins, functions and many other techniques that allow you to make CSS that is more maintainable, themable and extendable.»

We use Less to harness the power of variables to easily change page dimensions, crop marks & sizes generally. It is also generally a good idea to use a CSS preprocessor for your authoring experience. We use Less, but any of the SASS SCSS would work too.


We use them for the interface actions like: - zoom - jump to a page - view as spread - toggle hi- and lo-res images

For Chrome only (from version 29 to 33)

Experimental Webkit features

We use CSS regions to make text flow into different divs (just like a print layout software). As it is not fully implemented yet, you need to use a webkit-based browser and activate the «experimental web platform features». To do so, you can visit the URL:


And search in the long list for «experimental web platform features» to enable. (or the equivalent in the language of your browser)


Snapshots | iceberg

Inside this repository



Stéphanie Vilayphioushouted

— Start of the boilerplate in a TGV, back to its roots.
Nota: less CSS does not work in Chrome on local files.

Wednesday, 12th March 2014 - 12:10


Stéphanie Vilayphiougave away

— we don't need to force the page height with an empty image anymore

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphioudeclared

— Crop marks seem ok.

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphiouexpressed

— Using Scribus to check cropmarks length and offset.
We use Scribus as a template for cropmarks for compatibility in case of
PDFs made with HTML and some made in Scribus for the same object to
avoid confusion at the printing house.
(We had this issue with Balsamine flyers last year where the front side
was designed in Scribus and the back side with HTML.)

Wednesday, 12th March 2014 - 18:15


Stéphanie Vilayphiourevealed

— Page breaks

It seems that you can't have it all.
If you have a heading with a "page-break-after: avoid", and that the
paragraph after has a "page-break-inside: avoid", the latter will be
applied, but the heading won't come along on the new page.
You can then insert manual page breaks, either by setting a "page-break"
class to the heading, or add an empty <div> with a "page-break" class
where you want the new page to begin.

Wednesday, 12th March 2014 - 18:36


Stéphanie Vilayphiouclaimed

— read me to use it

Sunday, 23rd March 2014 - 15:01


Stéphanie Vilayphioustated

— Using CSS regions to flow content into pages (so that content is not
printed on the crop marks area).

Thursday, 27th March 2014 - 23:28


Stéphanie Vilayphioupeached

— Refining web regions.

Friday, 28th March 2014 - 00:30


Stéphanie Vilayphiousang

— Variables for margins.
Mirrored pages are possible (even for casperjs I think as I do not
use @page:left|right, but .page:nth-child(odd|even) with CSS regions.

Note: I'll make two separate documents to start a single paged document or a
double-sided document.

Friday, 28th March 2014 - 00:57


Stéphanie Vilayphioulet loose

— Pagination made in pure CSS!

Note: it's now located with the preview page (where crop marks are), it
should be in its own place, maybe an absolute div so that we can move it
easily around the page.

Friday, 28th March 2014 - 01:05


Stéphanie Vilayphioushouted

— Adding a class "spread" to the <html> tag will display your document in
spread within the browser.

Friday, 28th March 2014 - 01:16


Stéphanie Vilayphiouverbalised

— Some iceberg pictures to showcase the tool.

Friday, 28th March 2014 - 01:17


Stéphanie Vilayphioutold

— A class `.moveable` to position absolute objects on the page.
You can then drag and drop the object, resize it.
Then click on its "properties" button to copy/paste its properties (top,
left, width, height) to its style attributes in the HTML document.

Saturday, 5th April 2014 - 01:19


Stéphanie Vilayphiouinterpreted

— Started a roadmap in the file `TODO` (I find this word more accessible
to non-programmers).

Please tell us if you'd like things to be added in this TODO list.

Saturday, 5th April 2014 - 01:22


Stéphanie Vilayphiourendered

— Classes for image fitting. Mostly useful when used inside a .moveable

Saturday, 5th April 2014 - 23:10


Stéphanie Vilayphioudisclosed

— Internal links in PDF works magically with HTML anchored links.

Body is in absolute position to allow moveable elements go beyond the

Monday, 7th April 2014 - 13:14


Stéphanie Vilayphioudeclared

— Content is written in a separate HTML file to simplify editing.
Thanks to Alex for the super simple Jquery trick:

This avoids using a micro-framework and imposing yet another technology.

Monday, 7th April 2014 - 15:21


Stéphanie Vilayphiourendered

— Replace page-break by region-break.

Monday, 7th April 2014 - 15:26


Stéphanie Vilayphioudeclared

— .moveable elements don't work when loaded from the external HTML page of

A small introduction note in the example page itself + an external link
to the project repository.

Monday, 7th April 2014 - 16:58


Stéphanie Vilayphioutalked

— Simplified structure of the document. Now the container of the regions
flow is inside the master-page, containing crop-marks and folio.
This master page is now duplicated to the desired number of pages,
written in a variable at the top of `print.js` file.

Monday, 7th April 2014 - 17:01


Stéphanie Vilayphioucomplained

— Example of different possible usage of moveable elements combined
with fitting classes.

Monday, 7th April 2014 - 17:02


Stéphanie Vilayphiouinterpreted

— Updated the TODO after some tests. Still exciting!

Monday, 7th April 2014 - 17:03


Stéphanie Vilayphioutweeted

— Moving moveable elements on its own example page.

Monday, 7th April 2014 - 17:16


Stéphanie Vilayphioudivulged

— Some cleaning + documentation

Monday, 7th April 2014 - 17:48


Stéphanie Vilayphioucomitted

— A "Preview" button adding a class "export" to <html> and to see images in high resolution using the "data-hires" attribute.
[note: the new feature of multiple image sources "srcset" doesn't work
for printing cases. Maybe when the <picture> tag will be implemented?]

Tuesday, 8th April 2014 - 01:00


Stéphanie Vilayphioutweeted

— var everywhere

Tuesday, 8th April 2014 - 01:01


Stéphanie Vilayphiouunwrapped

— A "Debug" button to show/hide elements boxes.

Tuesday, 8th April 2014 - 01:05


Stéphanie Vilayphioutattled

— Add "text-rendering: optimizeLegibility" to everything.

Tuesday, 8th April 2014 - 01:08


Stéphanie Vilayphioutalked

— Added common ligatures and kerning to every element.

Tuesday, 8th April 2014 - 01:15


Stéphanie Vilayphioulet loose

— .gitignore file to avoid tracking temp and backup files

Tuesday, 8th April 2014 - 15:49


Stéphanie Vilayphiouinterpreted

— Forgot to track the image example for small resolution.

Tuesday, 8th April 2014 - 15:50


Stéphanie Vilayphiouconfessed

— Reorganize project structure.

Tuesday, 8th April 2014 - 15:58


Stéphanie Vilayphioublabbed out

— Includes a header and a footer.
You can specify the height of them in the variables at the top of
`print.less`. If `height = 0`, then it's like they don't exist.
You can also specify their content in the variables for easier use.
As an example, the header has a mirrored running title and the footer
has a pagination.

Tuesday, 8th April 2014 - 22:18


Stéphanie Vilayphiouwhispered

— Use Ghostscript to convert a PDF from RGB to CMYK.

./ input.pdf


Friday, 11th April 2014 - 00:23


Stéphanie Vilayphiousaid

— Use Ghostscript to check color separation. It outputs a tiff image, converted
to jpg, for each color channel, for each page.
In progress: generation of a webpage to have an interface to check those

./ input.pdf

Friday, 11th April 2014 - 00:27


Stéphanie Vilayphiouwhistled

— Fix img url in content.html and index.html

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiousaid

— Update documentation.

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiouinterpreted

— still some stuff to do...wq

Friday, 11th April 2014 - 00:58


Stéphanie Vilayphioulet on

— `` generates an HTML page to check color separation,
layering the different images for each channel and page.

Friday, 11th April 2014 - 18:50


Stéphanie Vilayphioutattled

— Jump to page XX.

Friday, 18th April 2014 - 23:13


Stéphanie Vilayphioustated

— Interface buttons stay white when activated.

Friday, 18th April 2014 - 23:15


Stéphanie Vilayphiouexpressed

— Y E S
Crop marks finally work directly in Javascript, even with lots of pages.
Wonder why it does not work on Balsa project though.

Saturday, 19th April 2014 - 00:17


Stéphanie Vilayphioushouted

— Page count start at 1.

Saturday, 19th April 2014 - 00:19


Pierre Huyghebaertbabbled

— Added some little explanations

Saturday, 19th April 2014 - 13:29


Stéphanie Vilayphioudiscovered

— Merge branch 'master' of

Tuesday, 29th April 2014 - 19:15


Stéphanie Vilayphiouexpressed

— bouton "preview" devient "hi-res"

Thursday, 29th May 2014 - 15:08


Stéphanie Vilayphioudisclosed

— cleaning repo

Thursday, 29th May 2014 - 15:15


Pierre Huyghebaertblabbed

— Added a few extra explanations from our Variable publication session

Thursday, 29th May 2014 - 14:41


Stéphanie Vilayphioutalked

— Merge branch 'master' of

Thursday, 29th May 2014 - 15:17


Stéphanie Vilayphiouverbalized

— add explanation of colorSeparation folder

Thursday, 29th May 2014 - 15:20


Stéphanie Vilayphioutweeted

— view as spread

Thursday, 29th May 2014 - 15:57


Stéphanie Vilayphiouverbalised

— "Hi-res" button outlines in red images with too small resolution (set
for 300 dpi, change number to "3" to "6" if you want to check for 600dpi).

Thursday, 29th May 2014 - 16:32


Stéphanie Vilayphioutold

— rm error in page number

Tuesday, 19th August 2014 - 14:12


Stéphanie Vilayphioupeached

— main section: overflow hidden

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphiouverbalized

— spread button

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphiouspilled the beans

— update todo

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphiousaid

— Visit http://localhost:8000/regions-polyfill.html to test CSS regions
with browsers which don't support this feature natively.

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphiougave away

— Added reset.css to regions-polyfill.html to avoid weird margins.

Tuesday, 19th August 2014 - 14:17


Stéphanie Vilayphiouwhistled

— Delete manual firing of CSS regions polyfill as it does not work on the fly but on loading.

Tuesday, 19th August 2014 - 14:59


Stéphanie Vilayphiouverbalized

— create pages by cloning the master page in polyfill

Tuesday, 19th August 2014 - 17:26


Stéphanie Vilayphioustated

— simplification of the naming : "preview-page" becomes simply "page", "page" becomes "main-section"

Tuesday, 19th August 2014 - 17:29


Ludispilled the beans

— TODO update from OSP day October 24th

Friday, 24th October 2014 - 15:23


Stéphanie Vilayphiouclaimed

— Merge branch 'master' of

Monday, 24th November 2014 - 10:20


Stéphanie Vilayphioustated

— spreads are back

Friday, 6th February 2015 - 11:16


Stéphanie Vilayphiousaid

— renamed print-marks into pages

Friday, 6th February 2015 - 11:46


Alexandre Leraypeached

— wip

Wednesday, 11th February 2015 - 13:17


Alexandre Leraylet out

— bump

Friday, 13th February 2015 - 11:13


Alexandre Leraybabbled out

— more changes

Sunday, 15th February 2015 - 23:20


Alexandre Lerayclaimed

— réorganisation des fichiers

Monday, 16th February 2015 - 00:39


Alexandre Lerayshouted

— Séparation du javascript

Monday, 16th February 2015 - 01:02


Stéphanie Vilayphioutalked

— Polyfill to make it work on Firefox and latest Chromium

Friday, 27th February 2015 - 12:29


Stéphanie Vilayphioupublished

— changed order of javascript to make the GO TO button work

Friday, 27th February 2015 - 12:41



— mega clean

Wednesday, 4th March 2015 - 17:25



— removed the iceberg images for now:
I realize that one confusing aspect of the previous screenshots for the Iceberg was the use of a screnshot of an interface inside of a web page which actually was a layout interface. Very confusing. I plan to replace the images for this suggested branch, and update the screenshots inside the iceberg too.

Wednesday, 4th March 2015 - 17:28



— restructuring the repo for ease of use: all libs, tools, partials, files are to be placed into assets/

Wednesday, 4th March 2015 - 17:44



— rather than describing the necessary files for the boilerplate to run, I opted to describe the anatomy of the repo. Still to describe in sections of README: editing the running title, how to name the pdf, how to understand the CSS pagination, how to use css regions

Wednesday, 4th March 2015 - 18:07



— rather than describing the necessary files for the boilerplate to run, I opted to describe the anatomy of the repo. Still to describe in sections of README: editing the running title, how to name the pdf, how to understand the CSS pagination, how to use css regions

Wednesday, 4th March 2015 - 18:13



— updates the content to Flatland

Wednesday, 4th March 2015 - 18:59


colmspilled the beans

— still a bug with text flowing over pagination

Wednesday, 4th March 2015 - 19:05


Stéphanie Vilayphiouargued

— rm margins of footer to correct its position

Wednesday, 4th March 2015 - 23:25


Stéphanie Vilayphioublabbed

— some fixes in the readme

Monday, 9th March 2015 - 23:53


Stéphanie Vilayphioulet out

— gros merge avec design de la page d'Alex + la restructuration Alex et Colm

Monday, 9th March 2015 - 23:59


Stéphanie Vilayphiouexpressed

— Restructuration du projet pendant le workshop OSP à la HEAR, Strasbourg.

In the "setup" folder, you can now edit local settings such as page
number, source of the content (which can be a remote URL like the export
URL of an Etherpad), page geometry…

Wednesday, 11th March 2015 - 14:53



— changing .txt to .md of the README

Tuesday, 10th March 2015 - 00:13



— sematics and formatting of the README now that I see it rendered in gh

Tuesday, 10th March 2015 - 00:31


colmspilled the beans

— more syntaxic / formatic changes to README

Tuesday, 10th March 2015 - 00:50



— adding in a 'to document' list

Tuesday, 10th March 2015 - 00:56


Stéphanie Vilayphioutattled

— Merge branch 'master' of

Wednesday, 11th March 2015 - 14:56


Stéphanie Vilayphiouironized

— Put back the zoom button from VJ14 publication.
It is made using `-webkit-transform` because using the browser zooming
feature makes the rendering engine recalculate the layout, ending in
slight differences in word wraps.

Wednesday, 11th March 2015 - 15:06



— adding items to the README, discussing with Steph about moving most 'advanced' items out of the main README over to a 'dev' type file'

Friday, 13th March 2015 - 23:21



— moving over some settings, cleaning workshop files, last commit in the train back from Strasbourg

Friday, 13th March 2015 - 23:27


Stéphanie Vilayphioutweeted

— Fixed spread view.

Thursday, 12th March 2015 - 09:52



— Merge branch 'master' of

Saturday, 14th March 2015 - 15:23


colmlet the cat out of the bag

— updates the example to have two columns

Tuesday, 17th March 2015 - 22:01


Pierre Huyghebaertargued

— Put the first launch before other operation to try to ease the learning curve, and some minor corrections

Monday, 23rd March 2015 - 13:05


Stéphanie Vilayphiousaid

— Some cleaning.
Put the 2columns example in an "examples" folder so that the boilerplate
stays as basic as possible.
Nota: you can use the class "recipient" to create a new box to flow

Monday, 23rd March 2015 - 15:40


Stéphanie Vilayphiouargued

— Put further documentation in "".

Added example cases:
- 2 columns layout
- offset pagination
- 1 layout per page
- master pages

Monday, 23rd March 2015 - 16:53


Stéphanie Vilayphiougave away

— New example page: we can load content from part of an existing webpage!

Monday, 23rd March 2015 - 23:20


Stéphanie Vilayphioubabbled out

— Making the color guides less confusing.
Redrawing the crop marks with less, as the 4 values for
background-position does not seem to work in Arora.

Tuesday, 24th March 2015 - 23:22


Stéphanie Vilayphioucried

— fix paper size (it was the same as the page size)

Tuesday, 31st March 2015 - 10:44


Stéphanie Vilayphiousaid

— fix spread view

Tuesday, 31st March 2015 - 11:01


Stéphanie Vilayphiouspoke

— readme small fixes

Thursday, 30th April 2015 - 05:46


Stéphanie Vilayphiouwhispered

— mixed inks screenshot

Thursday, 30th April 2015 - 06:41


Stéphanie Vilayphioutweeted

— balsa 2014-2015 poster season

Thursday, 30th April 2015 - 14:15


Stéphanie Vilayphiousaid

— master pages example a bit more telling → applied on odd and even pages

Thursday, 30th April 2015 - 16:35


Stéphanie Vilayphioucomplained

— Boilerplate content.html contains "Your text here" message.

Content.html in examples folder then uses a longer text.

Thursday, 30th April 2015 - 16:38


Stéphanie Vilayphiouargued

— rm jquery.ui and popelt from index.html → they are useful only for moveable elements

Thursday, 30th April 2015 - 16:49


Stéphanie Vilayphioulet on

— moveable elements example

Thursday, 30th April 2015 - 17:02


Stéphanie Vilayphiouunwrapped

— example of an image on a spread

Thursday, 21st May 2015 - 14:07


Stéphanie Vilayphiouverbalised

— Working on example "load external webpage":
example with Villa Arson diplômés 2015, replacing class name "page" into
"loaded page" so that it doesn't get the styles from the boilerplate.

Thursday, 9th July 2015 - 11:03


Stéphanie Vilayphiousang

— renamed css folder into less

Thursday, 9th July 2015 - 11:45


Stéphanie Vilayphiousaid

— rm call to page.js in index.html as the file doesn't exist anymore

Thursday, 9th July 2015 - 13:58


Stéphanie Vilayphioutold

— changing paths with the new name of less folder

Monday, 13th July 2015 - 13:14


Stéphanie Vilayphioulet on

— examples of polyfill usage: It works on Chromium and Firefox ! But the polyfill seems to also apply on webkit, although there is no need for it.

Monday, 13th July 2015 - 13:56


Stéphanie Vilayphioupublished

— missing files to make examples work

Monday, 13th July 2015 - 13:57


Stéphanie Vilayphioutattled

— cleaning in the styles + adding 1mm to paper-height in the @page statement, so that it doesn't make an empty page on Chromium

Monday, 13th July 2015 - 14:02


Stéphanie Vilayphiouclaimed

— update readme: describe new examples, browser versions

Monday, 13th July 2015 - 14:15


Stéphanie Vilayphioutalked

— crop marks in javascript/html as the CSS gradients did not print

Sunday, 13th July 2014 - 15:01


Stéphanie Vilayphioulet the cat out of the bag

— Re-organizing the files and README/Documentation.

New files: `debug.less` + `ui.less`

`typography.less` is now called `styles.less` and is located into the `setup`

NEW: a `start` file, which you can double-click to launch the
mini-server instead of going into a terminal.

Sunday, 13th July 2014 - 15:28


Stéphanie Vilayphiouwhistled

— Some more organization.

Main change: `page.less` is now called `layout.less` for easier

Sunday, 13th July 2014 - 15:58


Stéphanie Vilayphiouclaimed

— main.less was not updated

Sunday, 13th July 2014 - 16:14


Alexandre Leraycomitted

— L'interface et la structure sont désormais séparées

Friday, 10th July 2015 - 11:23


Stéphanie Vilayphiouspoke

— Merge branch 'gui' of into gui

Tuesday, 11th August 2015 - 14:25


Stéphanie Vilayphiourendered

— Renamed:
- index.html → document.html
- gui.html → index.html

Tuesday, 11th August 2015 - 14:27


Stéphanie Vilayphiouargued

— gui css

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphiouironized

— reversed order of input and labels for better legibility

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphioupublished

— hide crop marks in preview mode

Tuesday, 11th August 2015 - 15:48


Stéphanie Vilayphiouargued

— pagination + region-breaks example now actually showcases something

Tuesday, 11th August 2015 - 16:36


Stéphanie Vilayphiouverbalized

— Added a disclaimer regarding the examples which might use an older version of the boilerplate

Tuesday, 11th August 2015 - 16:38


Stéphanie Vilayphiousang

— removed commented Popelt commands from moveable.html

Tuesday, 11th August 2015 - 16:43


Stéphanie Vilayphioulet out

— spread.html example now showcases images (or other content) running on a spread.

Tuesday, 11th August 2015 - 17:07


Stéphanie Vilayphioushouted

— if `var content = ''`, then the story is not replaced by a file (used for examples)

Tuesday, 11th August 2015 - 17:08


Stéphanie Vilayphioulet the cat out of the bag

— toggle spread class on <body> rather than <html>

Tuesday, 11th August 2015 - 17:10


Stéphanie Vilayphiouspoke

— New example: display your document as a flatplan

Friday, 9th October 2015 - 13:08


Eric Schrijversaid

— Make start script work on OS X as well

when launched from Finder, the PWD needs to be set

Thursday, 7th April 2016 - 14:24


Eric Schrijveradmitted

— Load polyfill automatically on Chrome

Thursday, 7th April 2016 - 16:00


Eric Schrijverdiscovered

— Add some structure to the HTML content document so it is clear it is HTML

Thursday, 7th April 2016 - 16:12


Stéphanie Vilayphiouuttered

— an image in the content of the 'examples' folder

Thursday, 7th April 2016 - 16:25


Stéphanie Vilayphioupeached

— region-break adapted for polyfill

Thursday, 7th April 2016 - 16:26



— relink the localhost to the file document.html. No need anymore to use the polyfill file

Thursday, 26th May 2016 - 13:07


Antoinebrought out

— start print

Friday, 20th August 2021 - 15:26