Technique Web : Le positionement CSS

Essai de tutorial sur la manipulation des boîtes CSS et leur positionnement
en remplacement des tableaux conformément aux recommandation du W3C
sur la séparation des données de la mise en page.

Préambule

Les recommandations de notre maître à tous le W3C sont claires : il faut éviter d'employer les tableaux pour le positionnement et la disposition des éléments d'une page Web et ne les réserver que pour les données tabulaires selon la philosophie générale du Web moderne : séparer le fond de la présentation.

Donc ce sont les feuilles de styles CSS qui sont chargées de cette besogne. Mais ce n'est pas une sinécure ! Car, si lourds soient-ils, les tableaux ne posaient pas de problème de compréhension et se présentaient, sans différences notables, sous tous les navigateurs. Mais il n'en est pas de même pour les feuilles de style (CSS) qui ont leur logique propre et surtout que la dite logique est interprétée de façon parfois fort différente par les navigateurs.

Mais ne vous arrachez pas les cheveux, s'il vous en reste encore, et tonton William qui ne risque plus grand chose de ce côté là vous a concocté un petit tutorial sur le positionnement CSS (presque) sans peine.

Commençons donc par un cahier des charges. Un cahier des charges relate généralement le genre de truc que vous n'auriez jamais idée de faire, mais comme c'est votre petit client chéri (ou votre chef de service honni) qui vous le demande, vous ne pouvez pas refuser.

Donc un infâme papier sur lequel vous avez renversé la moitié de votre tasse à café vous donne le schéma d'un site Web dont seule compte, pour le moment, la disposition. Il vous faut donc, via le Web, le HTML et le CSS obtenir quelque chose qui ressemble à ceci :

un infâme crobard

fig. 1 - l'infâme dessin de la page Web à obtenir

Il va falloir maintenant transformer l'oeuvre de l'artiste (?) en un site Web ressemblant.

Phase 1 - La page HTML de base

Après avoir fini votre tasse (et ce qu'il en reste), la première chose à faire est de taper le contenu dans un fichier HTML concocté avec votre éditeur favori de programmes sources (Notepad++, par exemple, est parfait pour cet usage vous le trouverez ici, car il n'est pas utile de sortir la grosse artillerie comme Dreamweaver).

Pour tester les résultats obtenus il est indispensable de disposer des 3 navigateurs les plus utilisés actuellement à savoir, pour le monde Windows, Internet Explorer (v 6), Mozilla Firefox (v 1.5) et Opera (v 8.5). Ceci dit il n'est pas inutile de pouvoir voir ce que donne votre site sous Linux (avec Konqueror ou autre) et MacIntosh (avec Safari).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Le positionnement CSS (1ere partie)</title>
</head>

<body>
<p>Titre g&eacute;n&eacute;ral</p>
<p>Un texte quelconque dans l'en-t&ecirc;te &agrave; gauche </p>
<p>Un texte non moins quelconque dans l'en-t&ecirc;te au centre</p>
<p>Un texte pas plus malin dans l'en-t&ecirc;te &agrave; droite</p>
<p>Un texte, toujours aussi instructif , situ&eacute; dans le corps de la page HTML</p>
<p>Et pour finir et toujours aussi nul un texte dans le pied de page. </p>
</body>

</html>

Voici la page Web à ce stade (du pur texte) : positionnement_css_1.html

Phase 2 : Début de la mise en page

Après il va falloir réfléchir sérieusement. Ce site se compose de boîtes et il aurait été fort tentant de le faire en tableau quitte à définir le style CSS de chaque ligne ou cellule. Mais, dans cet exercice nous allons le faire en boîte virtuelles <div> en CSS pur sucre.

Outre le corps habituel en HTML réglementaire, la balise body, qui déterminera le fond hors cadre, il y aura la page sensu stricto délimitée par une surface prédéfinie de 950 pixels de large (pour pouvoir s'afficher sur tous les navigateurs disposant d'une résolution égale ou supérieure à 1024x768), centrée et entourée d'un cadre et disposant d'une image de fond propre.

Commençons à mettre cela en oeuvre.

La feuille de style sera interne puisqu'utilisée par ce seul fichier HTML et sera écrite entre les balises <head> sous la forme

<style type="text/css">
<!--
.......
-->
</style>

Tout l'intérieur est compris entre les balises de commentaires HTML <!-- --> afin de neutraliser toute interaction inoportune avec des navigateurs ne gérant pas ou mal le style CSS. Ceci dit les commentaires à l'intérieur d'une feuille de style CSS qu'elle soit extérieure ou intégrée, comme ici, dans la feuille HTML ne sont évidemment pas les mêmes, mais celui du langage C, à savoir /* et */

Donc écrivons ce qui se rapporte à la balise body et qui se résume juste à l'utilisation d'une image de fond répétée en mosaïque (option par défaut qu'il est donc inutile de préciser).

body {
background-image: url(images/fond.png);
}

la deuxième balise de style aura pour but d'enfermer tout le contenu dans un espace centré de 950 pixels de large et encadré. Elle aura son fond propre. Cette balise est la balise virtuelle div, de type block (comme les paragraphes <p>). Comme elle est unique elle sera dénommée par id plutôt que par class et préfixée dans la feuille de style par le signe dièse. Cette balise contient tout ce qui peut être définit par défaut dans la page Web puiqu'elle en sera le contenant supérieur (si l'on excepte body). On l'appellera #tout, ce qui est explicite.

#tout {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: medium;
background-image: url(images/verre_gris.gif);
background-repeat: repeat;
width: 950px;
padding-left: 10px;
border: 5px ridge #CC6633;
margin: auto;
}

Rien de bien particulier à ce contenu si ce n'est qu'une marge interne (padding-left) a été définie pour éviter que le texte colle au côté gauche. La bordure utilise un effet de relief qui ne fonctionnera pas avec tous les navigateurs (comme IE 6).

A ce stade tout le contenu est bien positionné dans la boîte principale : positionnement_css_2.html

Mais si nous chargeons cette page avec différents navigateurs, nous constatons une différence dans la marge qui sépare notre boîte principale du début de la zone client du navigateur. Autrement dit la marge n'est pas pareille. Ceci est dû à une interprétaion différente entre IE 6, d'une part, et Firefox/Opera, d'autre part. IE 6 a la détestable manie de coller une marge par défaut d'un interligne. Ce n'est pas laid en soi, mais comme ça ne fonctionne pas de la même façon avec ses autres collègues il convient de corriger ça. Nous allons tout normaliser avec une marge, pour tout le monde, de 20 pixels. Pour cela il faut ajouter dans body la ligne


....
margin: 0px;
padding: 20px 0px 0px;
...

et dans tout la ligne


...
margin: 0px auto auto;
...

Cette fois-ci le résultat obtenu dans positionnement_css_2a.html est bien le même dans tous les navigateurs.

Phase 3 : Le deuxième niveau d'imbrication

Donc il y a 3 contenants contenus dans le grand Tout : l'en-tête, le corps et le pied de page.

Rien de difficile en soi. A ceci près que ce sont des boîtes de 2e niveau elles hériteront donc des propriétés de tout et s'écriront sous la forme

#tout #en-tete {

A ne surtout pas confondre avec

#tout, #en-tete {

qui signifie que #tout et #en-tête vont avoir exactement les mêmes propriétés et que ces balises sont au même niveau alors que dans le premier cas, qui nous intéresse, #en-tete hérite des propriétés de #tout et se trouve donc au niveau secondaire.

Hérite ne veux pas dire que ces propriétés sont fixées, nous pouvons les changer si tel est notre bon plaisir. Ce que nous allons faire au niveau de l'image de fond. C'est très discutable au niveau du rendu esthétique, mais ça sera pédagogique. Donc voici à intégrer les trois nouvelles boîtes dépendantes #en-tete, #corps et #au-pied.

Pour faire du genre nous réduirons un peu leur largeur pour bien montrer leur imbrication dans #tout avec un retrait de 10 pixels. Donc width sera mis à 920 pixels (et non 930 car il faut tenir compte de la bordure donc 2 fois 5 pixels) et la hauteur de ces 3 parties à 150, 400 et 100 pixels respectivement.

#tout #en-tete {
background-image: url(images/bggrey5.jpg);
background-repeat: repeat;
height: 150px;
width: 920px;
}

#tout #corps {
background-image: url(images/F98.jpg);
background-repeat: repeat;
height: 400px;
width: 920px;
}

#tout #au-pied {
background-image: url(images/F19.jpg);
background-repeat: repeat;
width:920px;
height:100px;
}

Commençons par visualiser le résultat avec Internet Explorer. Esthétique mise à part le rendu manque d'un effet de symétrie des boîtes imbriquées. Ceci provient de ce que le positionnement, dans le flux de positionnement par défaut, ne tient pas compte des bordures. Il sera aisé de le corriger avec une instruction margin-left: 10px qui aura un effet de centrage. Un margin-top pour #en-tete et un margin-bottom pour #en-bas, tous deux de 20 pixels (il faut tenir compte de la marge externe de #tout décrétée par body) également fera du plus bon effet pour ménager une marge constante pour le cadre.

La page à ce stade : positionnement_css_3.html

Maintenant si vous regardez votre page avec Firefox et Opera vous allez faire la grimace : il y a une séparation non voulue entre les 3 boîtes. Inutile de vous précipiter pour ajouter des margin:0 aux marges apparentes le problème n'est pas là (les marges sont bien à 0 par défaut). Vous vous demanderez alors pourquoi IE tant décrié pour mal gérer les feuilles de style se comporte moins bien que Firefox et Opera, mieux placés de ce côté là.

C'est que le résultat, apparemment bon, d'IE résulte néanmoins d'une insufisance d'interprétation. La logique interne est que vous utilisez une balise block avec div. Cette balise a une marge mise à zéro. Mais vous y mettez immédiatement un paragraphe qui est aussi une balise block avec sa propre marge. Idem pour le dernier paragraphe contenu dans le block div quelque soit sa position d'ailleurs et qui provoquera une marge inférieure. Cette logique est tordue et on comprend très bien que bon nombre de webmestres ne décrochent pas de leurs bons vieux tableaux pour la présentation.

Alors que faire si on persiste dans le CSS ? Une solution consisterait a tout adresser en "position absolute" ce qui obligerait ces fichues boîtes à se mettre là où on veut (il suffit de décaler la position de la suivante en incorporant la hauteur de la précédente dans la marge supérieure). Mais cela présenterait l'inconvénient d'un code lourd et plus difficile à modifier. Une autre solution, bien plus simple, consiste à ne pas préfixer la première et la dernière écriture d'une boîte par une balise block donc soit ne rien mettre, soit utiliser la balise span s'il y a un style à appliquer outre celui par défaut défini dans la boîte. Dans l'exemple 4 il y a une ligne

<span>&nbsp;</span>

en première et dernière position dans chaque boîte div.

La page à ce stade : positionnement_css_4.html

Une autre solution consiste à définir la marge des paragraphes concernés à zéro.

Appliquons deux types de mise en forme :

Dans la boîte #corps, supprimons la balise span mais précédons la première ligne de texte par la balise de saut de ligne <br /> afin de décoller le texte du bord supérieur de la boîte. Dans les propriétés de style de corps précisons que nous voulons du texte en Arial, de taille moyenne, gras, bleu et centré comme ceci

font-family: Arial, Helvetica, sans-serif;
font-size: medium;
font-weight: bold;
color: #0000FF;
text-align: center;

L'ennui c'est que tout ce qui est dans la boîte suit ce format par défaut. Mais il suffit de redéfinir la balise p propre à cette boîte avec du Times Roman, normal, noir, aligné à gauche avec retrait de première ligne de 10 pixels comme ceci

#tout #corps p {
font-family: "Times New Roman", Times, serif;
font-size: medium;
color: #000000;
text-align: left;
text-indent: 10px;
}

Cela fonctionnera très bien mais la démarche n'est pas la plus logique. Il vaut mieux définir dans la boîte la police par défaut et surdéfinir la première ligne (généralement un sous-titre) qu'on mettra donc dans une balise span.

Dans la boîte #en-bas mettons la police en blanc en Arial normal avec retrait de 10 pixels.

margin-right: 0px;
font-family: Arial, Helvetica, sans-serif;
font-size: medium;
color: #FFFFFF;
text-indent: 10px;

Pour la première ligne nous la voulons en Verdana vert, de taille grande, gras et centrée. Mais le centrage est impossible avec une balise inline, il faut donc que nous utilisions une balise <p> et donc que nous précisions que nous ne voulons pas de marges.

#tout #au-pied #debut {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: large;
font-weight: bold;
color: #00FF00;
text-align: center;
margin: 0px;
}

A ce stade notre page est nantie de couleurs affreuses mais très exactement ce que nous voullions et elle se comporte pareillement dans tous les navigateurs. positionnement_css_5.html

Phase 4 : Imbrications de boîtes (suite, mais pas fin)

Maintenant que les superpositions de boîtes ne posent plus de problèmes (en principe), voyons ce qu'on peut faire en les imbriquant. Nous allons réaliser ce qui est classiquement fait en tableau : 2 lignes dont la deuxième comporte 3 cellules. La première ligne contiendra le titre général et les trois cellules 3 textes avec des bordures autour des cellules.

Commençons par les lignes

Elles seront appelées #ligne_1 et #ligne_2. La hauteur de la boîte #en-tete étant de 200 pixels, nous leur donneront respectivement 75 et 125 pixels de hauteur. On met les marges à zéro. On intègre maintenant ces lignes dans le code HTML comme ceci

<body>
<div id="tout">
<div id="en-tete">
<div id="ligne_1">
<p>Titre g&eacute;n&eacute;ral</p>
</div>
<div id="ligne_2">
<p>Un texte quelconque dans l'en-t&ecirc;te &agrave; gauche </p>
<p>Un texte non moins quelconque dans l'en-t&ecirc;te au centre</p>
<p>Un texte pas plus malin dans l'en-t&ecirc;te &agrave; droite</p>
<span>&nbsp;</span>
</div>
</div>

A part quelques décalages de lignes dûs aux effets block conjugués il ne se passe strictement rien au niveau aspect.

Mettons en forme le texte de la ligne 1 en Cooper Black rouge, de grande taille en supprimant les marges de son paragraphe sauf celle du haut qui aura une valeur de 20 pixels. Toutefois cette marge n'est vue que par Internet Explorer et laisse impassible Firefox et Opéra. C'est dans padding-top (marge supérieure interne qu'il faut la mettre). Ce qui est d'ailleurs plus logique.

#tout #en-tete #ligne_1 p {
font-family: "Cooper Black";
font-size: xx-large;
color: #FF0000;
text-align: center;
margin: 0px;
padding-top: 20px;
}

Phase 5 : Imbrication de boîtes (de la juxtaposition pour finir)

Jusque là nous n'avons fait que des supperpositions imbriquées et nous arrivons mainteant au morceau de bravoure : les juxtapositions. Car la ligne 2 sera composée de 3 boîtes côte à côte. #gauche, #centre et #droite. Pour être sûr du résultat nous les affublerons de bordures bleues, vertes et rouges de 5 pixels pour être sûr du résultat (la technique des bordures provisoires est utile en composant un vrai site que ce soit avec les tableaux ou les boîtes div car elle permet de bien visualiser les positions).

Nous disposons de 125 pixels dans #ligne_2 et nous allons ménager une marge de 10 pixels en haut et en bas soit une hauteur utile de 105 pixels. Pour les tailles, on s'exprimera en pourcentage, 25 % pour les boîtes gauche et droite et 50 % pour celle du centre.

Dans le texte HTM supprimons la balise span ainsi que les balises de paragraphe et mettons ces nouvelles boîtes en position (prenez la bonne habitude des programmeurs d'indenter vos balises et leurs contenus ça vous permettra de détecter ce qui a été mal écrit plus facilement).

<body>
<div id="tout">
<div id="en-tete">
<div id="ligne_1">
<p>Titre g&eacute;n&eacute;ral</p>
</div>
<div id="ligne_2">
<div id="gauche">
Un texte quelconque dans l'en-t&ecirc;te &agrave; gauche
</div>
<div id="centre">
Un texte non moins quelconque dans l'en-t&ecirc;te au centre
</div>
<div id="droite">
Un texte pas plus malin dans l'en-t&ecirc;te &agrave; droite
</div>
</div>
</div>

Bien sûr, c'était à prévoir, l'affichage ne correspond pas du tout à ce que l'on désire. IE 6 avec sa logique propre d'interprétation des marges aggrandit la boîte en-tête pour y loger les 3 boîtes superposées. Opera et Firefox ne redimensionne rien et met les contenus des boîtes centre et droite, privés de leur mise en forme, dans la boîte corps.

Comment arranger cela ?

Il va falloir utiliser le positionnement avec la valeur "absolute" et calculer au pixel les positions. Dans ce cas il vaut mieux renoncer au dimensionnement en pourcentage. N'oublions pas que les marges ne sont pas comprises dans les dimensions des boîtes donc si nous voulons une taille, bordures comprises, de 105 pixels il faudra définir la hauteur à 95 pixels. Nous délimiterons la largeur (donc hors bordures à 200 pixels). Donc pour la boîte gauche nous avons

#tout #en-tete #ligne_2 #gauche {
height: 95px;
width: 200px;
border: 5px solid #0000FF;
position: absolute;
margin: 10px 0px 0px;
}

Elle est parfaitement placée

La boîte centre reprendra la même philosophie à ceci près qu'il faut calculer la marge gauche à 210 pixels et la taille à la surface disponible (920 pixels) moins les deux boîtes gauche et droites bordures comprises de 210 pixels chacunes moins les bordures de la boite centre soit
920 - 210 - 210 - 5 - 5 = 490 pixels

#tout #en-tete #ligne_2 #centre {
height: 95px;
width: 500px;
margin-top: 10px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: 210px;
border: 5px solid #00FF00;
position: absolute;
}

Le positionnement est parfait !

Il ne reste plus qu'à placer la dernière. Si la taille est définie à 200 pixels de large il faudra juste calculer la marge de gauche : 210 pour la boîte gauche avec les bordures, 490 pour la boîte centre ce qui fait 710 pixels.

Tout s'ajuste parfaitement et pour tous les navigateurs.

Il ne reste qu'à configurer le texte selon ce qui a déjà été vu pour la boîte en-bas. Nous ne le traiterons pas à nouveau, il n'a plus de secret pour vous.

Le résultat final : positionnement_css_6.html est donc bien conforme à ce que nous voullions obtenir.

Conclusion :

Si l'on veut bien se donner la peine de rentrer dans leur logique propre, le positionnement dans des boîtes CSS n'est pas plus compliqué qu'avec les tableaux et offre une plus grande souplesse d'utilisation. La conformité aux recommandations du W3C n'est pas une clause universitaire, mais facilite grandement la lecture aux déficients visuels s'aidant de machines logicielles de lecture automatique. Rien que ce dernier point justifie le petit apprentissage supplémentaire.





Valid XHTML 1.1
Valid CSS 1.2
Les balises qui composent ce site ont été élevées en plein air et nourries exclusivement au grain