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 Vilayphioupeached

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

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

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphioupeached

— Crop marks seem ok.

Wednesday, 12th March 2014 - 18:14


Stéphanie Vilayphiourendered

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

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

— read me to use it

Sunday, 23rd March 2014 - 15:01


Stéphanie Vilayphioulet the cat out of the bag

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

— Refining web regions.

Friday, 28th March 2014 - 00:30


Stéphanie Vilayphioutattled

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

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

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

— Some iceberg pictures to showcase the tool.

Friday, 28th March 2014 - 01:17


Stéphanie Vilayphioudivulged

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

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

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

Saturday, 5th April 2014 - 23:10


Stéphanie Vilayphioubabbled

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

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

— Replace page-break by region-break.

Monday, 7th April 2014 - 15:26


Stéphanie Vilayphiouadmitted

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

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

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

Monday, 7th April 2014 - 17:02


Stéphanie Vilayphioubrought out

— Updated the TODO after some tests. Still exciting!

Monday, 7th April 2014 - 17:03


Stéphanie Vilayphioutalked

— Moving moveable elements on its own example page.

Monday, 7th April 2014 - 17:16


Stéphanie Vilayphioulet on

— Some cleaning + documentation

Monday, 7th April 2014 - 17:48


Stéphanie Vilayphioudeclared

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

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

Tuesday, 8th April 2014 - 01:05


Stéphanie Vilayphiouadmitted

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

Tuesday, 8th April 2014 - 01:08


Stéphanie Vilayphiouexpressed

— Added common ligatures and kerning to every element.

Tuesday, 8th April 2014 - 01:15


Stéphanie Vilayphiouverbalized

— .gitignore file to avoid tracking temp and backup files

Tuesday, 8th April 2014 - 15:49


Stéphanie Vilayphioulet the cat out of the bag

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

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

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

./ input.pdf


Friday, 11th April 2014 - 00:23


Stéphanie Vilayphiouunwrapped

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

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

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiouwhistled

— Update documentation.

Friday, 11th April 2014 - 00:30


Stéphanie Vilayphiouironized

— still some stuff to do...wq

Friday, 11th April 2014 - 00:58


Stéphanie Vilayphiouverbalized

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

— Jump to page XX.

Friday, 18th April 2014 - 23:13


Stéphanie Vilayphioucried

— Interface buttons stay white when activated.

Friday, 18th April 2014 - 23:15


Stéphanie Vilayphiouinterpreted

— 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 Vilayphiougave away

— Page count start at 1.

Saturday, 19th April 2014 - 00:19


Pierre Huyghebaertlet out

— Added some little explanations

Saturday, 19th April 2014 - 13:29


Stéphanie Vilayphiouspilled the beans

— Merge branch 'master' of

Tuesday, 29th April 2014 - 19:15


Stéphanie Vilayphioutweeted

— bouton "preview" devient "hi-res"

Thursday, 29th May 2014 - 15:08


Stéphanie Vilayphiouexpressed

— cleaning repo

Thursday, 29th May 2014 - 15:15


Pierre Huyghebaertstated

— Added a few extra explanations from our Variable publication session

Thursday, 29th May 2014 - 14:41


Stéphanie Vilayphioucomitted

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

— view as spread

Thursday, 29th May 2014 - 15:57


Stéphanie Vilayphioutattled

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

— rm error in page number

Tuesday, 19th August 2014 - 14:12


Stéphanie Vilayphiousaid

— main section: overflow hidden

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphioublabbed

— spread button

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphiouwhistled

— update todo

Tuesday, 19th August 2014 - 14:13


Stéphanie Vilayphioudiscovered

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

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

Tuesday, 19th August 2014 - 14:17


Stéphanie Vilayphiouunwrapped

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

— create pages by cloning the master page in polyfill

Tuesday, 19th August 2014 - 17:26


Stéphanie Vilayphiouexposed

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

— Merge branch 'master' of

Monday, 24th November 2014 - 10:20


Stéphanie Vilayphiourendered

— spreads are back

Friday, 6th February 2015 - 11:16


Stéphanie Vilayphioubabbled

— renamed print-marks into pages

Friday, 6th February 2015 - 11:46


Alexandre Lerayinterpreted

— wip

Wednesday, 11th February 2015 - 13:17


Alexandre Leraysaid

— bump

Friday, 13th February 2015 - 11:13


Alexandre Leraybabbled out

— more changes

Sunday, 15th February 2015 - 23:20


Alexandre Leraysaid

— réorganisation des fichiers

Monday, 16th February 2015 - 00:39


Alexandre Leraytattled

— Séparation du javascript

Monday, 16th February 2015 - 01:02


Stéphanie Vilayphiouuttered

— Polyfill to make it work on Firefox and latest Chromium

Friday, 27th February 2015 - 12:29


Stéphanie Vilayphioublabbed out

— 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



— still a bug with text flowing over pagination

Wednesday, 4th March 2015 - 19:05


Stéphanie Vilayphiouverbalized

— rm margins of footer to correct its position

Wednesday, 4th March 2015 - 23:25


Stéphanie Vilayphioubrought out

— some fixes in the readme

Monday, 9th March 2015 - 23:53


Stéphanie Vilayphiouexpressed

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

Monday, 9th March 2015 - 23:59


Stéphanie Vilayphioucomitted

— 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


colmlet the cat out of the bag

— adding in a 'to document' list

Tuesday, 10th March 2015 - 00:56


Stéphanie Vilayphioucomitted

— Merge branch 'master' of

Wednesday, 11th March 2015 - 14:56


Stéphanie Vilayphiouclaimed

— 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


colmlet on

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

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

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

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

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

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

Monday, 23rd March 2015 - 23:20


Stéphanie Vilayphiouadmitted

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

— fix spread view

Tuesday, 31st March 2015 - 11:01


Stéphanie Vilayphiouinterpreted

— readme small fixes

Thursday, 30th April 2015 - 05:46


Stéphanie Vilayphioudiscovered

— mixed inks screenshot

Thursday, 30th April 2015 - 06:41


Stéphanie Vilayphioucomplained

— balsa 2014-2015 poster season

Thursday, 30th April 2015 - 14:15


Stéphanie Vilayphioulet out

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

Thursday, 30th April 2015 - 16:35


Stéphanie Vilayphioustated

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

— moveable elements example

Thursday, 30th April 2015 - 17:02


Stéphanie Vilayphiouemited

— example of an image on a spread

Thursday, 21st May 2015 - 14:07


Stéphanie Vilayphiouspoke

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

— renamed css folder into less

Thursday, 9th July 2015 - 11:45


Stéphanie Vilayphioutold

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

Thursday, 9th July 2015 - 13:58


Stéphanie Vilayphiouspoke

— changing paths with the new name of less folder

Monday, 13th July 2015 - 13:14


Stéphanie Vilayphioulet out

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

— missing files to make examples work

Monday, 13th July 2015 - 13:57


Stéphanie Vilayphiouuttered

— 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 Vilayphiougave away

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

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

— Some more organization.

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

Sunday, 13th July 2014 - 15:58


Stéphanie Vilayphiourevealed

— main.less was not updated

Sunday, 13th July 2014 - 16:14


Alexandre Leraysaid

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

Friday, 10th July 2015 - 11:23


Stéphanie Vilayphioudivulged

— Merge branch 'gui' of into gui

Tuesday, 11th August 2015 - 14:25


Stéphanie Vilayphiouironized

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

Tuesday, 11th August 2015 - 14:27


Stéphanie Vilayphioubrought out

— gui css

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphiouclaimed

— reversed order of input and labels for better legibility

Tuesday, 11th August 2015 - 15:47


Stéphanie Vilayphioudeclared

— hide crop marks in preview mode

Tuesday, 11th August 2015 - 15:48


Stéphanie Vilayphioutalked

— pagination + region-breaks example now actually showcases something

Tuesday, 11th August 2015 - 16:36


Stéphanie Vilayphioudeclared

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

Tuesday, 11th August 2015 - 16:38


Stéphanie Vilayphiouverbalized

— removed commented Popelt commands from moveable.html

Tuesday, 11th August 2015 - 16:43


Stéphanie Vilayphioublabbed out

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

Tuesday, 11th August 2015 - 17:07


Stéphanie Vilayphiouconfessed

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

Tuesday, 11th August 2015 - 17:08


Stéphanie Vilayphiouspoke

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

Tuesday, 11th August 2015 - 17:10


Stéphanie Vilayphioulet out

— New example: display your document as a flatplan

Friday, 9th October 2015 - 13:08


Eric Schrijververbalized

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

— Load polyfill automatically on Chrome

Thursday, 7th April 2016 - 16:00


Eric Schrijverunwrapped

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

Thursday, 7th April 2016 - 16:12


Stéphanie Vilayphiouverbalized

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

Thursday, 7th April 2016 - 16:25


Stéphanie Vilayphioutattled

— 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