Des styles CSS pour optimiser l'impression papier

Quelque-chose qui est souvent oublié sur un site, c'est que les internautes peuvent décider de l'imprimer. C'est parfaitement compréhensible quand le contenu s'y prête, par exemple un site de recettes ou autres fiches pratique. Mais pour des raisons propres à chacun tout type de site peut finir sur du papier. Je vais ici vous donner quelques astuces pour réaliser une feuille de styles "basique" pour l'impression. Mais sachez que les possibilités à ce sujet peuvent être impressionnantes (par exemple la pagination automatique). Cependant je n'en parlerai pas dans cet article qui se veut plus global.

Insérer ses styles

Il y a plusieurs façon d'appeler ses déclarations CSS pour l'impression. Il n'y a pas vraiment de meilleure façon, c'est surtout selon vos besoins et vos préférences.

Via une balise <link>

Vous pouvez appeler plusieurs feuilles de styles sur un même site grâce à la balise <link>. Afin que votre feuille de styles ne soit prise en compte que lors d'une impression, il faudra bien penser à renseigner l'attribut media avec la valeur print. Par exemple :

<link rel="stylesheet" type="text/css" href="print.css" media="print" />

Via une media query

Vous pouvez également faire le choix de n'avoir qu'une seule feuille de style et dans celle-ci de faire une section dédiée à l'impression. C'est par exemple ce qui est fait dans le framework Knacss. Il suffira alors d'inclure tous les styles dédiés dans une simple media query @media print, comme ça :

@media print {
    /*
    Et ici, on met tous les styles pour l'impression ! :)
    */
}

Les unités et quelques règles typographiques pour l'impression

Tout d'abord, qui dit impression dit (en général) papier. Et donc on utilisera des unités plus adaptées. Notamment le point (pt) pour le texte, ou les cm / mm pour d'autres dimensions.

La taille du texte

Pour le texte, si vous avez pour habitude d'utiliser l'unité rem, c'est super. Il ne vous reste alors plus qu'à redéfinir le font-size de html. Si vous utilisez la méthode qui fait que 1rem = 10px (font-size de html à 62.5%), il vous faudra recalculer en fonction de la taille souhaitée et de votre taille de base sur écran. Par exemple, la taille de base du texte d'un site est 16px, soit 1.6rem (en général déclarée sur body). Sur ce site, je souhaite avoir une taille de base de 12pt. Il suffit donc de calculer la taille de texte de html T pour faire en sorte que T x 1.6 = 12. Donc T = 12 / 1.6 = 7.5pt :

html{ font-size: 7.5pt; }

Toutes vos autres tailles seront recalculées proportionnellement à leur version écran (en tout cas celles où vous avez utilisé des rem et des em). Attention cependant, cette technique ne marche que si vos styles d'impression viennent se cumuler à vos styles pour écran. Sinon il vous faudra redéfinir vos tailles de texte au cas par cas, avec par exemple :

body{ font-size: 12pt; }

Bien sûr, concernant le body vous pouvez cumuler les deux méthodes. Puisque si vous n'utilisez pas de rem, le font-size du html ne sera pas utilisé. Alors que celui du body restera le même que vous mettiez 1.6rem ou 12pt (dans mon exemple en tout cas).

Éviter les veuves et orphelines

Bah pourquoi ? Elles ont rien demandé les pauvres !

Parce que c'est moche :)

En typographie, une veuve est la dernière ligne d'un paragraphe qui apparaît seule en haut d'une page ou à la fin d'une colonne. Une orpheline, c'est pareil mais dans l'autre sens. C'est la première ligne d'un paragraphe qui apparaît seule en bas de page ou en début de colonne. Dans ces cas là, on voudrait plutôt faire en sorte qu'au moins deux ou trois lignes du paragraphe coupé sur plusieurs pages ou colonnes apparaissent ensemble. Et en CSS, c'est possible grâce aux propriétés widows et orphans. Il faudra alors leur indiquer le nombre de lignes minimales que l'on doit laisser groupées :

p{
    orphans: 3;
    widows: 3;
}

Gestion des coupures et des pages

Dans la même lignée qu'une orpheline, avoir un titre tout seul en bas de page puis son contenu sur la page suivante ce n'est pas l'idéal. Ou encore couper une liste en deux. De même, on peut décider qu'un titre de niveau 1 commence toujours sur une nouvelle page. C'est une mauvaise idée, mais techniquement on peut. Tout ça se gère grâce aux propriétés (page-)break-before, (page-)break-after et (page-)break-inside, avec notamment la valeur avoid.

Attention, j'ai mis (page-) entre parenthèses parce qu'en CSS2 on utilisait la forme page-break-*, qui est encore en service, mais la forme break-* arrive bientôt avec également la gestion des colonnes. Ici j'anticipe et je mets les deux formes, on n'est plus à ça près :)

/* pas de coupure de page à l'intérieur de ces éléments */
blockquote, ul, ol{
    page-break-inside: avoid;
    break-inside: avoid;
}

/* pas de coupure de page après ces éléments */
h1, h2, h3, h4, h5, h6, caption{
    page-break-after: avoid;
    break-after: avoid;
}

Et tu parlais du titre de niveau 1 tout à l'heure, comment je peux faire ça et pourquoi tu trouves que c'est une mauvaise idée ?

Tu peux faire ça avec la valeur always : h1{ page-break-before:always; }, ce qui mettra toujours le titre au début d'une page. Sauf qu'un site a rarement plus d'un titre de niveau 1, ce qui limite les risques de coupure, en revanche celui-ci peut avoir un peu de contenu avant, ce qui résulterait en une première page d'impression vide ou presque.

Choisir ce qui sera imprimé

La question de l'utilité et de la pertinence d'imprimer certaines parties du site peut se poser. On peut facilement imaginer qu'imprimer le menu de navigation ou tout autre élément interactif sera inutile. En général, quand un internaute imprime une page en particulier, c'est pour son contenu. Et à moins que vous ne souhaitez garder le logo de votre site sur toutes les impressions, vous pouvez décider de supprimer le header, le footer, et tous les éléments annexes. Et pour ça, un simple display:none sur ces éléments fera très bien l'affaire ! :)

Une classe on/off

Vous pouvez donc sélectionner ces éléments avec leur classe. Ou créer une classe dédiée comme dans mon exemple suivant avec la classe noprint. J'ai aussi décidé d'y mettre une classe printonly qui sera utilisée sur des éléments que je ne veux voir qu'à l'impression. J'y ajoute également !important au cas où d'autres classes ou styles inline auraient un poids plus fort et rendraient mes éléments visibles par accident. Certains seraient tentés d'afficher .printonly avec un display:block, mais je ne le recommande pas. Parce que rendre un élément visible ce n'est pas forcément block, mais aussi inline, flex, table... En ce qui me concerne, j'opte plutôt pour une paire de media queries, une avec l'opérateur not, l'autre sans.

@media print{
    .noprint{ display: none !important; }
}
@media not print{
    .printonly{ display: none !important; }
}

Qui s'applique ainsi :

<div class="noprint">Je serai visible tout le temps, sauf à l'impression.</div>
<div class="printonly">Je ne serai visible qu'à l'impression.</div>

Anticiper et gérer les éléments inadaptés

Il peut vous arriver d'avoir à gérer des éléments qui ne se prêtent pas bien à l'impression. Je pense notamment aux carrousels, aux onglets/accordéons, aux zones de taille limitée avec gestion du scroll... Il faudra bien anticiper la gestion de ces éléments si vous voulez optimiser vos impressions. Dans la mesure du possible, on évitera alors d'utiliser des propriétés comme height par exemple. Ou encore d'appliquer vos règles qui structurent ce type d'élément dans une media query de type screen. Et garder l'affichage non structuré sur les autres supports.

Afficher les liens

Les liens n'étant plus cliquables à l'impression (si si, j'vous jure !), il peut être intéressant de les afficher à l'impression si jamais l'internaute veut pouvoir y accéder par la suite. Ceci dit, ça reste assez délicat pour plusieurs raisons :

  • Des liens, il y en a partout sur un site, du header au footer. Si vous n'avez pas masqué ces parties, vous risqueriez d'en avoir dans tous les sens.
  • Certains liens pointent vers des ancres, ou encore vers des appels javascript.
  • Enfin, certains liens sont quand même assez imbitables. Réécrire à la main des urls à rallonge pleines de variables et de codes alphanumériques abstraits est assez fastidieux.

Les deux premiers problèmes peuvent être évités facilement avec uniquement une déclaration CSS bien faite. De mon côté, je suis parti du principe que les liens "intéressants" seraient très probablement dans des balises <p>, et qu'ils avaient bien sûr un attribut href. Dans ma façon d'intégrer les sites ça se tient, après libre à vous de l'adapter à la vôtre. Ensuite, j'élimine les liens dont l'attribut href commence par "#" ou par "javascript:". Vous pourriez aussi à la place cibler uniquement les liens qui commencent par "http" ou par "/". C'est plus restrictif mais ça peut se justifier. Après avoir ciblé nos liens, on leur ajoute l'url à la suite directement en css, ce qui nous donne le code suivant :

p a[href]:not([href^="javascript:"]):not([href^="#"])::after{
    content: " (" attr(href) ")";
    opacity: 0.8;
    font-size: 0.8em;
}

En ce qui me concerne j'ai aussi décidé de les rendre plus discrets avec opacity et font-size.

Simplifier les liens

Pour le troisième problème de ma liste, vous pourriez ajouter une classe à ces liens pour empêcher l'apparition de l'url. Ou forcer une autre url que vous auriez défini à la main dans un attribut data-lienprint par exemple. Si je complète mon exemple précédent, on aurait alors ceci :

p a[href]:not([href^="javascript:"]):not([href^="#"])::after{
    content: " (" attr(href) ")";
}
p a[data-lienprint]::after{
    content: " (" attr(data-lienprint) ")";
}
p a[href]:not([href^="javascript:"]):not([href^="#"])::after,
p a[data-lienprint]::after{
    opacity: 0.8;
    font-size: 0.8em;
}

Avec le code HTML suivant, le texte entre parenthèses serait "Recherche de «the answer to life, the universe and everything» sur https://www.google.com". Dans cet exemple ça reste long, mais quand même beaucoup plus clair pour l'internaute.

<a
   href="https://www.google.com/search?q=the+answer+to+life%2C+the+universe+and+everything&rlz=1C1CHBD_frFR840FR840&oq=the+answer+to+life%2C+the+universe+and+everything&aqs=chrome..69i57j6j0.1263j0j8&sourceid=chrome&ie=UTF-8"
   data-lienprint="Recherche de «the answer to life, the universe and everything» sur https://www.google.com">
    Un exemple de lien
</a>

Faire des économies à l'internaute

Une des principales contraintes liées à l'impression, c'est la consommation d'encre. Celle-ci, au litre, coûte allègrement son millier d'euro. Le but n'est donc pas d'en tartiner des pages entières. La plupart des navigateurs l'ont d'ailleurs bien compris. Ils désactivent souvent par défaut l'impression des couleurs et images de fond, ainsi que les ombres portées. Pour mieux maîtriser ce que vous faites, vous pouvez donc déjà supprimer les fonds et ombres de vos éléments.

*{
    background: transparent !important;
    box-shadow: none !important;
    text-shadow: none !important;
}

Si vraiment vous voulez forcer l'impression du fond, vous pouvez utiliser la propriété color-adjust / -webkit-print-color-adjust avec la valeur exact. Mais ne comptez pas trop là-dessus : c'est une propriété non standard dont la couverture reste faible.

Concernant le texte, vous pouvez passer sa couleur (y compris pour les titres et liens) en noir. Il y a plusieurs raisons à ça :

  • Sur certaines imprimantes, le cyan, magenta et jaune peuvent être dans une seule et même cartouche, et le noir dans une cartouche à part. Il arrive même que la cartouche de noir contienne plus d'encre que les autres couleurs. Dans ces cas là, utiliser du noir fera que l'internaute changera moins souvent ses cartouches.
  • Avec les fonds qui sont ignorés, la couleur qui offrira le plus de contrastes (que le papier soit blanc ou non) sera le noir. Pour la lisibilité, c'est mieux :)
  • En évitant de colorer le texte, vous gardez le contrôle sur le rendu une fois imprimé. Votre couleur, si l'internaute imprime la page en niveau de gris plutôt qu'en couleur, pourrait passer en gris assez pâle et être moins lisible que dans sa couleur d'origine.

Gérer les images pour l'impression

Laisser les images telles qu'elles sont est une bonne chose :)

Mais avec un peu d'imagination, vous pouvez envisager d'autres alternatives. En voici quelques-unes qui me viennent en tête.

Supprimer les images, tout en gardant leur "trace"

Vous pouvez décider que vos images n'apportent rien d'important, et que les enlever ne changera rien à la compréhension de votre page. Dans ce cas là, il peut être utile, plutôt que de faire un simple display:none, d'afficher l'emplacement d'une image et d'écrire à la place son texte de remplacement. Le problème, c'est que si on reprend la technique du lien pour afficher l'attribut alt en ::before ou ::after et que l'on masque l'image, on masquera par la même occasion le pseudo-élément. On peut donc utiliser à la place la balise figure, et afficher la balise figcaption qu'elle contiendra tout en masquant l'image. Ce qui nous donne en HTML puis en CSS :

<figure>
    <img src="mon-image.jpg" />
    <figcaption>Description de mon image</figcaption>
</figure>
img{
    display: none;
}
figure{
    /* Styles purement arbitraires, à changer selon vos goûts :) */
    border: 1px solid #ccc;
    padding: 1rem 2rem;
}
figure figcaption{
    display: block;
    margin: 0;
    padding: 0;
}
figure figcaption::before{
    /* Ajout d'un préfixe avant le texte pour préciser qu'il s'agissait d'une image */
    content: "Image : ";
}

À la place de mon image j'aurai donc un rectangle au contour gris clair dans lequel il sera écrit "Image : Description de mon image".

Optimiser les images

Dans la même veine que la couleur du texte, on peut choisir de "forcer" les images à être en noir et blanc, même si l'impression se fait en couleurs. Dans ce cas là, on peut également forcer un peu le contraste pour accentuer les tons clairs et foncés. Voici trois exemples de rendus :

Image originale
La même image, désaturée
L'image désaturée et contrastée

Pour obtenir ce résultat, il n'y a qu'à jouer avec la propriété filter ! :) Dans mon exemple, j'ai fait comme ça :

img{
    filter: contrast(150%) grayscale(100%);
}

On peut aussi ajouter la valeur brightness(n)n vaudra plus de 100% pour éclaircir davantage les images (et donc consommer moins d'encre). Ou alors jouer sur l'opacité dans ce cas là, mais quitte à avoir la propriété filter en place autant simplement lui rajouter une valeur :)

Et voilà, il n'est pas toujours évident de concevoir le fait qu'un site puisse être imprimé, mais avec ces quelques conseils votre site sera déjà plus "propre" si quelqu'un décide de l'imprimer.

Si vous avez trouvé cet article intéressant, pourquoi ne pas le partager ? :)
Facebook Messenger Twitter LinkedIn Viadeo Reddit Email

Vous avez une remarque, une précision à apporter, ou quelque-chose vous échappe ?
N'hésitez pas à participer à cet article, cet espace est pour vous !

Personne n'a encore commenté cet article.

Mais il faut bien un début à tout, pas vrai ?

Commenter, poser une question...

 

Ces articles pourraient également vous intéresser

Tout savoir sur les media queries pour un site responsive design réussi

Sur les media-quoi ? Responsive design ? Bon, si vous êtes ici c’est que vous avez déjà au moins entendu parler de ces termes, et probablement que vous savez également de quoi il s’agit. Pour les autres, voici un petit récapitulatif !

Lire l'article Tout savoir sur les media queries pour un site responsive design réussi
Remonter