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 Vilayphiourevealed

— 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 Vilayphioupublished

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

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphiouadmitted

— Crop marks seem ok.

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphiouverbalized

— 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 Vilayphioucomitted

— 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 Vilayphioulet the cat out of the bag

— read me to use it

Sunday, 23rd March 2014 - 15:01


Stéphanie Vilayphioutold

— 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 Vilayphioushouted

— Refining web regions.

Friday, 28th March 2014 - 00:30


Stéphanie Vilayphioubabbled

— 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 Vilayphiousang

— 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 Vilayphiousang

— 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 Vilayphioudivulged

— Some iceberg pictures to showcase the tool.

Friday, 28th March 2014 - 01:17


Stéphanie Vilayphioulet the cat out of the bag

— 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 Vilayphioubabbled

— 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 Vilayphioutalked

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

Saturday, 5th April 2014 - 23:10


Stéphanie Vilayphioublabbed

— 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 Vilayphiouexpressed

— 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 Vilayphioulet the cat out of the bag

— Replace page-break by region-break.

Monday, 7th April 2014 - 15:26


Stéphanie Vilayphioutweeted

— .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 Vilayphiouexpressed

— 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 Vilayphiouconfessed

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

Monday, 7th April 2014 - 17:02


Stéphanie Vilayphioudeclared

— Updated the TODO after some tests. Still exciting!

Monday, 7th April 2014 - 17:03


Stéphanie Vilayphioudisclosed

— Moving moveable elements on its own example page.

Monday, 7th April 2014 - 17:16


Stéphanie Vilayphiouexposed

— Some cleaning + documentation

Monday, 7th April 2014 - 17:48


Stéphanie Vilayphiouspoke

— 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 Vilayphioudiscovered

— var everywhere

Tuesday, 8th April 2014 - 01:01


Stéphanie Vilayphiouuttered

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

Tuesday, 8th April 2014 - 01:05


Stéphanie Vilayphiousaid

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

Tuesday, 8th April 2014 - 01:08


Stéphanie Vilayphioubabbled

— Added common ligatures and kerning to every element.

Tuesday, 8th April 2014 - 01:15


Stéphanie Vilayphioudivulged

— .gitignore file to avoid tracking temp and backup files

Tuesday, 8th April 2014 - 15:49


Stéphanie Vilayphiouwhispered

— Forgot to track the image example for small resolution.

Tuesday, 8th April 2014 - 15:50


Stéphanie Vilayphioubabbled out

— Reorganize project structure.

Tuesday, 8th April 2014 - 15:58


Stéphanie Vilayphiouemited

— 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 Vilayphioulet loose

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

./ input.pdf


Friday, 11th April 2014 - 00:23


Stéphanie Vilayphiouadmitted

— 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 Vilayphiouspilled the beans

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

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiourevealed

— Update documentation.

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiousaid

— still some stuff to do...wq

Friday, 11th April 2014 - 00:58


Stéphanie Vilayphiouunwrapped

— `` 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 Vilayphiouargued

— Jump to page XX.

Friday, 18th April 2014 - 23:13


Stéphanie Vilayphioulet out

— Interface buttons stay white when activated.

Friday, 18th April 2014 - 23:15


Stéphanie Vilayphiouargued

— 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 Vilayphioutattled

— Page count start at 1.

Saturday, 19th April 2014 - 00:19


Pierre Huyghebaertspilled the beans

— Added some little explanations

Saturday, 19th April 2014 - 13:29


Stéphanie Vilayphiouverbalised

— Merge branch 'master' of

Tuesday, 29th April 2014 - 19:15


Stéphanie Vilayphiouemited

— bouton "preview" devient "hi-res"

Thursday, 29th May 2014 - 15:08


Stéphanie Vilayphiougave away

— cleaning repo

Thursday, 29th May 2014 - 15:15


Pierre Huyghebaertexpressed

— Added a few extra explanations from our Variable publication session

Thursday, 29th May 2014 - 14:41


Stéphanie Vilayphioulet on

— Merge branch 'master' of

Thursday, 29th May 2014 - 15:17


Stéphanie Vilayphiousaid

— add explanation of colorSeparation folder

Thursday, 29th May 2014 - 15:20


Stéphanie Vilayphiouspoke

— view as spread

Thursday, 29th May 2014 - 15:57


Stéphanie Vilayphiouwhistled

— "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 Vilayphioutattled

— rm error in page number

Tuesday, 19th August 2014 - 14:12


Stéphanie Vilayphioulet out

— main section: overflow hidden

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphioubabbled out

— spread button

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphioutold

— update todo

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphioulet loose

— 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 Vilayphiouunwrapped

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

Tuesday, 19th August 2014 - 14:17


Stéphanie Vilayphioudivulged

— 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 Vilayphioubabbled

— create pages by cloning the master page in polyfill

Tuesday, 19th August 2014 - 17:26


Stéphanie Vilayphiouinterpreted

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

Tuesday, 19th August 2014 - 17:29



— TODO update from OSP day October 24th

Friday, 24th October 2014 - 15:23


Stéphanie Vilayphioublabbed

— Merge branch 'master' of

Monday, 24th November 2014 - 10:20


Stéphanie Vilayphioubabbled

— spreads are back

Friday, 6th February 2015 - 11:16


Stéphanie Vilayphiouadmitted

— renamed print-marks into pages

Friday, 6th February 2015 - 11:46


Alexandre Lerayclaimed

— wip

Wednesday, 11th February 2015 - 13:17


Alexandre Leraycomitted

— bump

Friday, 13th February 2015 - 11:13


Alexandre Lerayargued

— more changes

Sunday, 15th February 2015 - 23:20


Alexandre Leraycried

— réorganisation des fichiers

Monday, 16th February 2015 - 00:39


Alexandre Leraysaid

— Séparation du javascript

Monday, 16th February 2015 - 01:02


Stéphanie Vilayphioubabbled out

— 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


colmbrought out

— 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


colmlet out

— 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



— still a bug with text flowing over pagination

Wednesday, 4th March 2015 - 19:05


Stéphanie Vilayphiouexpressed

— rm margins of footer to correct its position

Wednesday, 4th March 2015 - 23:25


Stéphanie Vilayphioulet the cat out of the bag

— some fixes in the readme

Monday, 9th March 2015 - 23:53


Stéphanie Vilayphiouconfessed

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

Monday, 9th March 2015 - 23:59


Stéphanie Vilayphioulet on

— 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



— 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 Vilayphioutalked

— Merge branch 'master' of

Wednesday, 11th March 2015 - 14:56


Stéphanie Vilayphiouargued

— 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 Vilayphiouconfessed

— Fixed spread view.

Thursday, 12th March 2015 - 09:52



— Merge branch 'master' of

Saturday, 14th March 2015 - 15:23



— updates the example to have two columns

Tuesday, 17th March 2015 - 22:01


Pierre Huyghebaertblabbed out

— 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 Vilayphioutattled

— 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 Vilayphiouadmitted

— 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 Vilayphioupublished

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

Monday, 23rd March 2015 - 23:20


Stéphanie Vilayphioubabbled

— 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 Vilayphiousaid

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

Tuesday, 31st March 2015 - 10:44


Stéphanie Vilayphiouironized

— fix spread view

Tuesday, 31st March 2015 - 11:01


Stéphanie Vilayphioutold

— readme small fixes

Thursday, 30th April 2015 - 05:46


Stéphanie Vilayphioustated

— mixed inks screenshot

Thursday, 30th April 2015 - 06:41


Stéphanie Vilayphioudeclared

— balsa 2014-2015 poster season

Thursday, 30th April 2015 - 14:15


Stéphanie Vilayphiousang

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

Thursday, 30th April 2015 - 16:35


Stéphanie Vilayphiourevealed

— 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 Vilayphioustated

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

Thursday, 30th April 2015 - 16:49


Stéphanie Vilayphiouuttered

— moveable elements example

Thursday, 30th April 2015 - 17:02


Stéphanie Vilayphiouconfessed

— example of an image on a spread

Thursday, 21st May 2015 - 14:07


Stéphanie Vilayphioubrought out

— 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 Vilayphioubabbled

— renamed css folder into less

Thursday, 9th July 2015 - 11:45


Stéphanie Vilayphiouinterpreted

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

Thursday, 9th July 2015 - 13:58


Stéphanie Vilayphiouadmitted

— changing paths with the new name of less folder

Monday, 13th July 2015 - 13:14


Stéphanie Vilayphiouemited

— 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 Vilayphioulet loose

— missing files to make examples work

Monday, 13th July 2015 - 13:57


Stéphanie Vilayphiourevealed

— 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 Vilayphioutold

— update readme: describe new examples, browser versions

Monday, 13th July 2015 - 14:15


Stéphanie Vilayphiourendered

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

Sunday, 13th July 2014 - 15:01


Stéphanie Vilayphiouverbalised

— 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 Vilayphiouunwrapped

— Some more organization.

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

Sunday, 13th July 2014 - 15:58


Stéphanie Vilayphioudisclosed

— main.less was not updated

Sunday, 13th July 2014 - 16:14


Alexandre Lerayblabbed out

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

Friday, 10th July 2015 - 11:23


Stéphanie Vilayphiouexposed

— Merge branch 'gui' of into gui

Tuesday, 11th August 2015 - 14:25


Stéphanie Vilayphiousang

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

Tuesday, 11th August 2015 - 14:27


Stéphanie Vilayphioubabbled out

— gui css

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphiouspoke

— reversed order of input and labels for better legibility

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphiouinterpreted

— hide crop marks in preview mode

Tuesday, 11th August 2015 - 15:48


Stéphanie Vilayphiouconfessed

— pagination + region-breaks example now actually showcases something

Tuesday, 11th August 2015 - 16:36


Stéphanie Vilayphioutalked

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

Tuesday, 11th August 2015 - 16:38


Stéphanie Vilayphioubabbled

— removed commented Popelt commands from moveable.html

Tuesday, 11th August 2015 - 16:43


Stéphanie Vilayphiouinterpreted

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

Tuesday, 11th August 2015 - 17:07


Stéphanie Vilayphioupeached

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

Tuesday, 11th August 2015 - 17:08


Stéphanie Vilayphioutalked

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

Tuesday, 11th August 2015 - 17:10


Stéphanie Vilayphiouwhispered

— New example: display your document as a flatplan

Friday, 9th October 2015 - 13:08


Eric Schrijvergave away

— 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 Schrijverlet the cat out of the bag

— Load polyfill automatically on Chrome

Thursday, 7th April 2016 - 16:00


Eric Schrijverlet the cat out of the bag

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

Thursday, 7th April 2016 - 16:12


Stéphanie Vilayphiouexpressed

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

Thursday, 7th April 2016 - 16:25


Stéphanie Vilayphioushouted

— 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



— start print

Friday, 20th August 2021 - 15:26