Comment générer une impression horizontale dans une page web.

Récemment, pour mon travail, j'ai eu à générer des pages de statistiques s'étendant parfois assez loin horizontalement (plusieurs écrans). Un autre formatage n'était pas vraiment possible puisque les statistiques descendaient aussi sur plusieurs écrans vers le bas. De plus, j'utilisait déjà la "3e dimension", grâce à un menu permettant de n'afficher qu'une année à la fois (l'équivalant des onglets Windows). Jusque là, le système n'est pas parfait, mais est correcte puisque ce gros tableau est ce que veux l'usager (il a choisi lui-même son contenu). Il n'a qu'à utiliser les "scroll bar" pour visualiser son contenu.

Sécable ou insécable.

Cependant, l'usager désire aussi imprimer ce tableau. Et là, surprise ! Il n'en obtient que les premières colonnes. Pour comprendre cette réaction du browser, il faut connaître une notion de l'affichage web : les objets insécables. Un objet insécable est un objet qui ne peut pas logiquement être couper et poursuivi à la ligne suivante. Ainsi, une image est insécable puisqu'elle ne sera pas affichée sur deux lignes si elle ne rentre pas sur la page (ou l'écran). Un paragraphe n'est pas insécable puisque les différents mots qui le composent peuvent être séparés par un saut de ligne s'il manque d'espace. En redimensionnant votre fenêtre, le contenu de ce paragraphe s'adaptera à l'espace disponible; les sauts de lignes seront ailleurs. Et pour les tableaux ? Les cellules composant le tableau ne sont pas insécables. Elles se comportent comme les paragraphes. Si vous n'avez pas assigné une largeur aux cellules ou au tableau, elles s'adapteront à l'espace disponible. Ce pendant, les rangs qui forment le tableau sont insécables. Une cellule affichée sur le premier rang ne se retrouvera pas au second s'il manque d'espace. Au mieux, elle se rétrécira jusqu'à n'afficher qu'un mot par ligne (un texte sans espace, tel qu'un mot, est insécable). La largeur minimale d'un rang sera donc la somme du mot le plus long de chaque cellule, plus les marges. La largeur minimale du tableau sera celle du rang le plus long.

Donc, le tableau est en partie insécable. S'il est plus grand que l'espace disponible sur la page à l'impression, le browser ne peut pas en couper une partie pour la rapporter en dessous, alors... il en coupe une partie quand même, laquelle n'est pas affichée du tout. Bon, à l'écran c'est bien. On a notre scroll bar et on va voir plus loin au besoin. Mais sur papier, je préférerais avoir la suite de mon tableau en dessous, puisque je peux, après l'impression, la remettre "manuellement" à côté. Il faudrait que j'appelle Bill pour le lui dire...

Trouver la solution

De façon générale, tout problème de programmation web a déjà une solution sur un forum. Il suffit simplement au programmeur d'être assez débrouillard pour l'adapter. Mais ce n'est pas le cas de ce problème. Du moins, je n'ai vraiment rien trouvé, à part d'essayer d'imprimer en paysage pour voir si ça sort mieux. Si quelqu'un connaît un autre site qui traite du sujet, laisser le moi savoir.

Moi, j'ai codé ma solution personnelle, avec ses avantages et ses inconvénients sur une impression normale. J'ai par la suite décidé d'écrire cette page pour aider d'autres personnes avec le même problème. Bon, je ne suis diplômé que depuis quelques mois. Je ne suis pas un webmaster senior. C'est un peu prétentieux de vouloir déjà écrire un tutorial, mais je crois tout de même que cette page peut servir à d'autre. Avant d'aller plus loin, je veux aussi souligner que cette solution se base sur la norme CSS 2. Elle a donc une compatibilité limitée. En fait, comme les grands browsers rechignent pas mal à intégrer la norme CSS à leurs outils, seul Internet Explorer 5 et plus sera en mesure d'afficher correctement à l'écran un tableau formater pour l'impression horizontale. Il faudra faire deux pages distinctes pour les autres navigateurs.

Un tableau logique, plusieurs tableaux physiques.

Il faut d'abord mettre quelques détails au clair. Premièrement, un élément insécable reste insécable, et il n'y a absolument rien qu'on peut y faire. Deuxièmement, Internet Explorer coupe la fin d'un élément insécable s'il est trop gros horizontalement. Il est donc tronqué à l'impression. On ne peut rien y faire non plus. Je ne connais pas les possibilités des autres browsers, mais je crois qu'ils ont le même défaut. La seule solution envisageable, selon moi, est de créer plusieurs tableaux et de les disposer de façon à ce qu'ils aient l'air de n'en former qu'un seul. Si, par exemple, le tableau prend trois pages, il faut faire trois tableaux. Chaque rang du tableau sera donc scindé en trois rangs plus petits qui seront les rangs correspondant (1er, 2e, etc) de chaque sous tableau.

Ce n'est pas plus compliqué que cela. Mais le problème, c'est que les tableaux s'affichent un sous l'autre à l'écran aussi, alors que nous voulons construire un tableau large. Si vous voulez faire une page accessible à tous les usagers de l'internet, ou si vous ne voulez simplement pas vous compliquer la vie, créé une copie de votre gros tableau en plusieurs petits tableaux et rediriger l'usager voulant l'imprimer vers cette page. Cependant, je n'aime pas dédoubler le code, et j'ai travaillé sur un site optimisé pour Internet Explorer. Avec IE 5.0+, on peut faire mieux.

L'attribut display

L'attribut CSS display permet de gérer la façon dont un élément sera affiché. Le W3C prévoit 17 valeurs pour cet attribut. Là-dessus, trois sont pris en charge par Netscape, et 5 par Internet Explorer. La plupart des gens ont utilisé les valeurs block et none, qui permettent d'ajouter ou retirer un élément dans l'affichage. Une autre valeur possible si l'on veut voir l'élément à l'affichage est inline. La différence entre un élément block et un élément inline est qu'il y a un saut de ligne après un élément block. Par exemple, la valeur par défaut de l'attribut display d'un paragraphe (balise p) est block, car le paragraphe est toujours suivi d'un saut de ligne. Par contre, l'image (balise img) utilise la valeur inline, car la suite du document se situe immédiatement après l'image (sans saut de ligne). Le tableau (balise table), lui, a la valeur block par défaut. C'est pourquoi nos petits tableaux sont affichés un sous l'autre. En affectant le code CSS suivant aux tableaux, ont peux les transformer en éléments inline, et les voir s'afficher un à côté de l'autre. Malheureusement, Netscape ne prend pas en charge cette instruction.

    display:inline;

La largeur de l'écran

Une fois l'attribut display modifié, il est probable que vous ne voyez pas de différence. En fait, vous n'en verrez pas si la largeur du tableau est à peu près celle de l'écran. C'est que les éléments inline sont suivis d'un saut de ligne s'il n'y a plus d'espace disponible pour l'afficher sur la première ligne (comme notre paragraphe qui se redimensionne). Il faut donc leur donner plus d'espace. Il vous suffit de mettre vos tableaux dans une balise div, et de lui assigner une largeur supérieure (width:300%;  /* exemple */). Ça y est ! Nos tableaux sont maintenant bien disposés.

Configurer l'impression

Il reste un dernier problème à solutionner. Si on ne change rien, l'impression sera identique à l'affichage à l'écran. On revient à la case départ, avec un gros tableau tronqué... Heureusement, la norme CSS 2 prévoit 8 propriétés d'impression. Ce sont des propriétés qui servent uniquement à configurer la sortie à l'imprimante. Internet Explorer en supporte deux (aucune pour Netscape). Nous allons utiliser la propriété page-break-before. Comme son nom l'indique, cette propriété fait un saut de page avant l'élément. Le code suivant devrait donc terminer notre tâche.

    page-break-before:always;

Pour ceux qui ne sera pas au courant, vous pouvez aussi changer le style des éléments sur l'imprimante seulement. La norme CSS 2 prévoit la possibilité d'affecter une feuille de style à un média en particulier. Ce média peut être l'écran (screen) ou l'imprimante (print). Vous pouvez donc styliser votre page de la façon suivante :

<link rel="stylesheet" type="text/css" href="stylesGeneraux.css" />
<link rel="stylesheet" type="text/css" href="stylesEcran.css" media="screen" />
<link rel="stylesheet" type="text/css" href="stylesImpr.css" media="print" />

Un exemple

Pour terminer, voici un exemple un peu forcé du principe décrit plus haut. Il s'agit d'une table de multiplication des nombres de 1 à 12, dont les cellules ont été grossies pour qu'elles prennent plus d'une page en tout. Notez que ce qui semble être un tableau à l'écran en est quatre dans le code. La bordure noire qui trace une croix au centre du tableau vous montre où se terminent les pages. Selon les besoins de l'usager, on peut laisser cette bordure pour lui montrer clairement de quoi aura l'air la sortie imprimante, ou la masquer en jouant avec les attributs border-top-width, border-left-width, etc, de façon à n'avoir qu'une bordure autour du tableau logique.

Notez aussi qu'il y à une feuille de style qui modifie la page pour l'impression uniquement. Il est important de redéfinir l'attribut display à block pour l'impression. Autrement, les sauts de pages ne se feront pas aux bons endroits. J'ai aussi changé les mesures des cellules du tableau, puisque l'unité de mesure px ne devrait être utilisée qu'à l'écran.

Hosted by www.Geocities.ws

1