Paged.js
Paged.js est une bibliothèque JavaScript open-source permettant de concevoir un contenu paginé dans un navigateur et de générer des documents PDF destinés à l’impression, en utilisant les langages du web (HTML, CSS et JavaScript).
Elle est aujourd’hui l’un des outils les plus performants pour le web to print, particulièrement lorsque l’on veut concevoir des documents multi-pages.
Par où commencer ?
1 — Un navigateur web : Ungoogled Chromium ou Chromium (à défaut, Edge ou Chrome)
2 — Un serveur web : paged.js en a besoin pour être exécuté. Si on utilise VSCode, le plus simple est l’extension live server (Go Live).
Serveur local avancé
Si on a MAMP, on peut travailler dans le dossier htdocs
. Si on a Herd, où on veut parmi les sites configurés.
Si on est sous OSX / linux, dans un terminal :
cd votre/dossier/de/travail
php -S localhost:8888
# ou bien
python -m SimpleHTTPServer 8888
# ou bien
python3 -m http.server 8888
# ces 3 commandes permettent d’accéder à la page web sur http://localhost:8888
3 — Un code source de base : télécharger ce fichier zip.
4 — Un onglet ouvert sur la documentation : pagedjs.org/documentation !
Comment ça marche ?
La librairie Paged.js permet de transformer un document “flux” en un document “paginé”, capable d’utiliser différents gabarits de pages, d’afficher des titres courants ou des numéros de pages, de générer une table des matières, etc.
L’exécution de paged.js va transformer le code-source HTML & CSS en un ensemble complexe d’éléments et de styles qui permettent de prévisualiser dans le navigateur le comportement de l’impression ou la génération de PDF.
Le “polyfill” paged.js transforme la totalité du document pour en prévisualiser l’impression.
↑ Dans le contexte d’un projet web + print, pour plus de simplicité, on fera volontiers une entorse au principe du single source publishing en créeant deux documents HTML ; l’un pour l’affichage écran, l’autre pour l’impression (qui incluera l’appel javascript au polyfill et aux feuilles de style nécessaires : à la fois l’interface et les styles personnalisés pour le print).
Définir le format du document
Paged.js utilise les spécifications CSS prévues depuis CSS 2.1 (voir la section précédente).
On peut définir le format de page et les marges grâce à la règle @page
.
@page {
size: 148mm 210mm;
margin: 1cm;
}
/* on peut également définir des comportements différents pour les
pages de gauche et de droite ; ici, les “petits” et “grands fonds”
– marges intérieures et extérieures – sont inversés */
@page :left{
margin: 33mm 23mm 65mm 45mm;
}
@page :right{
margin: 33mm 45mm 65mm 23mm;
}
On peut également déterminer des repères de coupe et une marge de fond perdu :
@page {
/* … */
marks: crop;
bleed: 4mm;
}
Paged.js générera alors un ensemble d’éléments HTML et de variables CSS qui permettront de mettre en pages le contenu et ses marges. Lire dans la documentation, la règle @page.
Voir exemple 01.
Définir des gabarits de page
Pour spécifier des “types” de pages singuliers (entrées de chapitre, couverture, page d’iconographie, etc.), on affecte une class
à un élément du HTML. En CSS, on déclare une nouvelle page-type, puis on affecte cette page-type à cette .class
grâce à une déclaration page: typedepage
. Lire dans la documentation, les pages nommées.
<header class="couverture">
<h1>Titre</h1>
<h2>Sous-titre</h2>
</header>
@page macouverture {
margin: 0;
background: black;
}
.couverture {
page: macouverture;
color: white;
}
Voir exemple 02.
Ajouter des numéros de page et des titres courants
Les margin boxes créées par Paged.js peuvent accuillir du contenu: généré automatiquement, tels des numéros de page, ou présents dans le HTML (section courante, titre du document, etc.).
@page :left{
@bottom-left {
content: counter(page);
}
}
@page :right{
@bottom-right {
content: counter(page);
}
}
/* pas de numéro de page pour la couverture */
@page macouverture {
@bottom-right { content: none; }
@bottom-left { content: none; }
}
Voir exemple 03.
Paged.js offre d’autres possibilités que les compteurs de page, notamment grâce aux propriétés string-set et position: running (lire la documentation :). Ici, un exemple avec position: running()
:
<section>
<p class="title">Titre courant</p>
<h1>…</h1>
<p>…</p>
</section>
/* supprime l’élément .title de l’affichage grâce à la déclaration position: running() */
.title {
position: running(monTitreCourant);
}
/* injecte l’élément définit dans running() dans une margin-box */
@page {
@top-center {
content: element(monTitreCourant)
}
}
Voir exemple 04.
Aller plus loin
Ces principes de base permettent de mettre en pages un contenu relativement rapidement. Mais de nombreuses possibilités graphiques peuvent encore être explorées, chacune demandant une approche spécifique. Ci-dessous viendront s’ajouter des liens vers des résolutions concrètes, des exemples plus complexes ou des problèmes courants.
Pour comprendre, téléchargez les examples et examinez leur code source.
- Générer une table des matières
- Gérer des notes de bas de page
- Double-page avec une seule image
- Exécuter du javascript avant ou après l’action de Paged.js
- Imposer le document pour une impression directe en livret
- Éxécuter Paged.js à la demande
- Recharger le document à la même page en cas de modification css/html
- Rendre interactive chaque page d’un livre
- Peindre les lettres d’un livre
On peut aussi parcourir les exemples de Julien Taquet sur gitlab.pagedmedia.org ou sur codepen.io/julientaq, les experiments sur le gitlab de PagedMedia, ou les démos de Raphaël Bastide / PrePostPrint.
Un espace de discussion et de support est accessible sur le Mattermost de coko.foundation. Julien Taquet et l’équipe de Paged.js y répondent aux questions des utilisateur·ices, quelque soit leur niveau de compétences ;)