Steve Frécinaux

CSS: Découpage d’une interface simple

Puisqu’on me le demande, je redépose ici un petit didacticiel sans prétention aucune et qui n’est sans doute pas sans inexactitudes dans la prose ou dans la technique. Il s’agit du découpage d’une interface signée Kedfré et de la mettre en place via CSS. À ma décharge et comme excuse aux inexactitudes, je citerai l’âge de la chose : presque un an…

Donc n’hésitez surtout pas à me signaler les erreurs, j’avoue ne pas avoir relu la chose !

L’interface “globale”

### L’interface### Il s’agit d’une interface créée par Kedfré dans photoshop pour son portfolio, qui n’est pas encore en ligne à l’heure actuelle. Elle se divise en deux parties principales : le menu à gauche, et le contenu à droite. Beaucoup d’éléments doivent être placés au pixel près. Voici l’interface non-découpée.

Nous allons en faire un fichier XHTML+CSS valide en quelques minutes…

Première partie : le contenu

Le contenu est donc la partie de droite. On peut facilement voir sur l’image ci-dessus que l’on peut diviser cette partie en trois : le haut, le bas et le milieu, qui se répète. Voici les trois images que l’on peut en tirer (je ne m’étendrai pas sur la partie découpage mais plus sur la partie CSS), respectivement droite-top.jpg, droite-fond.gif et droite- bottom.jpg.

Le code XHTML

On va maintenant générer le code XHTML qui va avec :

<!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" />
  <link rel="stylesheet" type="text/css" href="style.css" media="all" />
</head>
<body>
<div id="page">
<div id="volet_droit">
  <div class="top"></div>
  <div class="contenu">
    <h1>Kedfre's portfolio</h1>
    <p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla vitae mauris nec elit
    tempor ullamcorper. Proin vitae purus at lectus sodales porta. Ut consequat. Nunc ut
    dui. Morbi ipsum. Ut scelerisque placerat felis. Aenean euismod urna in felis. Vivamus
    accumsan purus sit amet tortor. Donec euismod, felis a pretium dictum, libero risus
    adipiscing mi, non lacinia pede mauris id wisi. Praesent ultrices leo in odio. Sed ut
    ligula. Mauris ac ipsum non diam gravida faucibus.
    </p>
    [...]
  </div>
  <div class="bottom"></div>
</div>
</div>
</body>
</html>

La première ligne est le type de document. Il est nécessaire pour le xhtml et conseillé dans tous les cas. Voici pourquoi. La 4e ligne contient le jeu de caractère utilisé. Il est toujours utile de le spécifier, pour éviter à certain de bien mauvaises surprises (une mauvaise détection de jeu de caractère peut donner des résultats assez… étranges). Ensuite vient le lien vers le fichier css, ici baptisé simplement “style.css”.

C’est après la balise <body> que les choses intéressantes commencent :
d’abord vient <div id="page">. Il s’agit d’un div qui contiendra toute la page. Il sera utile par la suite pour centrer l’interface, nous y reviendront par la suite.
Le calque volet_droit commence juste après. Pour faciliter la mise en place de l’interface, j’ai un peu triché : j’ai divisé volet_droit en trois divs, dont un div vide avant et un div vide après. Ce nous sera utile pour mettre en place les images droite-haut.jpg et droite-bas.jpg.
Dans le calque dont la classe est “contenu”, se trouve le contenu à proprement parler : un titre ainsi qu’un texte bidon.

Le code CSS

Si vous regardez la page à ce stade vous n’allez pas voir grand chose de bien excitant, mais nous allons maintenant mettre de la peau sur ce squelette. Voici le code de style.css :

#volet_droit {
  background:url("droite-fond.gif") repeat-y;
  width:556px;
  left:224px;
}
#volet_droit .top {
  background:url("droite-top.jpg") no-repeat;
  width:556px; 
  height:40px;
  margin:0;
}
#volet_droit .bottom {
  background:url("droite-bottom.jpg") no-repeat;
  width:556px; 
  height:37px;
  margin:0; 
}
#volet_droit .contenu {
  height:330px;
  overflow:auto;
}

En gros que faisons-nous dans ce petit css ? Tout d’abord nous définissons la largeur et la hauteur du volet droit, simplement en regardant la taille de celui-ci dans le logiciel ayant servi à la découpe. Ensuite nous définissons comme arrière plan l’image droite-fond.gif, affichée plus haut, qui est une image de 1px de haut et qui forme ainsi le fond de la partie. Nous faisons en sorte que cet arrière-plan se répète en hauteur uniquement, via repeat-y.
Après, nous faisons de même pour le haut et le bas du cadre volet_droit : on définit leur largeur et hauteur (qui sont en fait les dimensions des images droite-top.jpg et droite-bottom.jpg) et l’on place la bonne image en fond, en évitant toute répétition via no-repeat. Vous aurez sans doute remarqué que les identifiants commençant par # se rapportent aux id dans le code xhtml, et que les identifiants commençant par . se rapportent aux class. #volet_droit .top signifie ainsi “l’élément dont la classe est ‘top’, qui est imbriqué dans l’élément dont l’id est ‘volet_droit’”. Quand au contenu, nous définissons sa hauteur et nous lui attribuons la propriété overflow:auto, ce qui va avoir pour résultat de fixer la hauteur du div (quelle que soit la longueur de son contenu), et de faire apparaître une barre de défilement si le contenu est trop important pour la hauteur disponible, ce qui est souhaité si l’on regarde l’interface.

Si l’on regarde maintenant le résultat, on peut remarquer que le texte dépasse des limites “graphiques” de l’interface, et que la barre de défilement n’est pas positionnée sur l’élément prévu.
En ajoutant ceci :

margin:0 16px 0 11px;
padding:5px 28px 5px 5px;

Dans le style volet_droit .contenu, vous pouvez remarquer qu’on obtient le résultat désiré. En fait, ici, margin sert à positionner la limite extérieure du cadre .contenu dans ses limites graphiques (margin est en fait la marge extérieure du cadre), tandis que padding (la marge intérieure) positionne le texte de façon plus “jolie”, dans la zone grise et sans toucher les ombrages.
Les 4 valeurs de margin (et de padding) correspondent dans l’ordre à la marge du haut, de droite, du bas et de gauche, et ont aussi été mesurées directement dans le logiciel graphique. Le texte est maintenant positionné correctement, et notre volet droit est magnifique ;)

Deuxième partie : le volet du menu

Pour cette partie, j’ai décidé de faire de façon simple. Cependant il n’est pas interdit de procéder comme pour la partie droite… Je vais ici donner directement les codes XHTML et CSS, sans les développer, car il n’y a rien d’intéressant à en sortir pour l’instant. Le code HTML est à placer entre les lignes<div id="page"> et <div id="volet-droit">, et le CSS peut être placé au début de style.css.

<div id="menu">
</div>

#menu {
  width:232px;
  height:240px;
  background:transparent url("gauche-fond.jpg") no-repeat;
}

Menu

Si vous regardez l’interface dans l’état actuel, vous remarquez que le contenu se trouve sous le menu et non à sa gauche.

Troisième partie : positionnement

#### Positionnement absolu#### Il nous faut donc positionner notre menu de façon correcte, à gauche du menu. Pour celà nous allons utiliser les positionnements absolus, car, à cause des ombrages bitmaps, il faut que le menu chevauche de contenu sur quelques pixels, et les positionnements absolus sont la façon la plus simple de procéder dans ce cas.
Les positionnements absolus sont en fait des positionnements par rapport aux bordures du haut et de gauche de la page.
Nous ne toucherons pas au code XHTML à cette étape. Nous allons uniquement modifier la css.

Commençons par le menu, qui doit être positionné en haut à gauche.

#menu {
  width:232px;
  height:240px;
  background:transparent url("gauche-fond.jpg") no-repeat;
  position:absolute;
  left:0px;
  top:0px;
}

position:absolute indique au navigateur que nous passons du mode de positionnement normal au positionnement absolu pour cette boite. left et top indiquent la distance entre les bordures du haut et de gauche. À noter que pour une mesure de 0, il n’est pas nécessaire de spécifier les unités (en effet, 0px = 0px = 0cm = 0% = … = 0). Cependant, indiquer les unités est obligatoire dans tous les autres cas.

z-index

À ce stade, le menu disparait sous le contenu. Nous allons donc positionner ce dernier. (Les dimentions ont encore une fois été prises directement sur l’image.)

#volet_droit {
  background:transparent url("droite-fond.gif") repeat-y;
  width:556px;
  position:absolute;
  top:4px;
  left:224px;
}

Si l’on regarde ce que ça donne, on voit que le contenu chevauche toujours le menu, ce qui provoque une ligne bleue disgratieuse. Normalement le menu doit chevaucher le contenu pour que nous ayons le même visuel que dans le logiciel graphique. Nous allons donc travailler les z-index du menu et du contenu. Le z-index est en fait la “hauteur” du calque sur l’axe z (axe perpendiculaire à la dalle de l’écran). Plus il est élevé, et plus il se place “au dessus” des autres calques. Donc un calque ayant un z-index élevé chevauchera un calque ayant un z-index faible.
Rajoutons donc z-index:1; dans le style de #volet_droit, et z-index:2; dans le style de #menu. Regardez… Miracle, l’interface ressemble tout à fait à l’image de départ

Centrage et fond

Le fond blanc, avouez que ce n’est pas top… Et comme la taille de l’interface est fixe, pourquoi ne pas la centrer dans la fenêtre du navigateur ? Personne n’aime les petites interfaces ramassées en haut à gauche… Encore une fois pas besoin de modifier le XHTML, quelques lignes de css feront l’affaire. Vous vous souvenez du div “page” ? Bah c’est le moment de l’utiliser :

body  {
  background-color:#284157;
  text-align:center;
}
#page {
  height:411px;
  width:780px;
  text-align:left;
  margin:13px auto;
  position:relative;
}

L’indentifiant body et tous les identifiants sans signe devant se réfèrent directement aux balises dont ils portent le nom. Ici nous définissons une couleur d’arrière-plan (le bleu sombre de l’interface). Nous spécifions aussi que le texte dedans doit s’aligner au centre. Il s’agit en fait d’une mauvaise interprétation des css par Internet Explorer, qui va ainsi nous permettre de centrer l’interface.

En dessous nous avons le style de #page. Nous commençons par définir sa hauteur et sa largeur (mesurées encore et toujours sur l’image de départ). Il est nécessaire de les définir, car par défaut un div a une largeur de 100%, et n’est donc pas centrable… text-align:left remet l’alignement du texte à la normale (sans quoi le contenu serait centré lui aussi). margin:13px auto; définit les marges verticales et horizontales. Définir des marges auto à gauche et à droite permet de centrer une boite (div, p, h1, etc.), conformément à ce qu’a dit le w3c. la dernière ligne, position:relative, donne une consistence au calque “page”, sans quoi le positionnement absolu des boites qu’il contient se ferait toujours par rapport au point en haut à droite de la fenêtre. De cette façon on force le positionnement à s’effectuer par rapport au point en haut à gauche du calque “page”.

Le contenu

### Le volet de droite### Rien de bien compliqué, nous allons nous limiter à des styles basiques, car ce n’est pas le sujet de l’article ;)

#volet_droit .contenu p {
  color:#ffffff;
  font:12px/14px verdana, arial, sans-serif;
  text-decoration:none;
  background:#a6b3bb;
  margin:5px;
}
#volet_droit .contenu h1{
  color:#fff;
  font:bold 12px verdana, arial, sans-serif;
  font-weight:bold;
  border-bottom:1px solid  #284157;
  margin:2px;
}

Le menu

#### Un menu habituel en XHTML#### Nous allons mettre en place le menu de la page. Remplacez donc <div id="menu"></div> par ceci :

<div id="menu">
  <ul>
    <li><a href="#" class="menu1"><span>Sites web</span></a></li>
    <li><a href="#" class="menu2"><span>Sites mobiles</span></a></li>
    <li><a href="#" class="menu3"><span>Interfaces</span></a></li>
    <li><a href="#" class="menu4"><span>Illustrations</span></a></li>
    <li><a href="#" class="menu5"><span>Pixel-art</span></a></li>
    <li><a href="#" class="menu6"><span>C.V.</span></a></li>
    <li><a href="#" class="menu7"><span>Contact</span></a></li>
  </ul>
</div>

Il s’agit d’une liste à puces (<ul>). En XHTML, il est de bon ton de présenter les menus sous cette forme. Ne vous inquiétez pas, à l’affichage, on ne verra même pas qu’il s’agit d’une liste. Vous pouvez aussi voir que chaque lien renferme un . Ce span sera utilisé pour remplacer chaque lien par une image (c’est aussi pour cela que chaque lien a une classe “menuX”). Le code XHTML est maintenant définitif.

#menu ul {
  margin:74px 54px 0 43px;
  padding:0;
  list-style-type:none;
  display:block;
}
#menu li { margin:0; padding:0; display:inline; border:none; }
#menu a {
  display:block;
  margin:0px;
  padding:0px;
}

Ce code css dont à insérer sous les styles #menu.
Le style du ul permet, dans l’ordre, de positionner le menu dans les limites “graphiques” de l’interface (margin), de supprimer les marges intérieures, de masquer les puces et d’afficher le ul comme une boite (comme les divs) plutôt que comme une liste. Le style du li enlève toute les marges et affiche le li comme un élément in-line (comme , ou par exemple). Il s’agit en fait de corriger une bizarrerie de IE, qui sans cette transformation en in-line, affiche toujours des marges, très gênantes.

Pour le a, on l’affiche aussi sous forme de boite (display:block) pour pouvoir par après y coller une image (ce qui n’est pas faisable de façon efficace sinon).

Ajoutons maintenant les images de fond (menuX.gif) :

#menu a {
  display:block;
  margin:0px;
  padding:0px;
  height:12px;
  width:135px;
  margin-bottom:6px;
}

#menu span { display:none; }

#menu .menu1 { background:url("menu1.gif") no-repeat; }
#menu .menu2 { background:url("menu2.gif") no-repeat; }
#menu .menu3 { background:url("menu3.gif") no-repeat; }
#menu .menu4 { background:url("menu4.gif") no-repeat; }
#menu .menu5 { background:url("menu5.gif") no-repeat; }
#menu .menu6 { background:url("menu6.gif") no-repeat; }
#menu .menu7 { background:url("menu7.gif") no-repeat; }

Nous affichons donc les liens sous forme de boites, dont nous définissons la largeur et la hauteur. Nous définissons aussi une marge de dessous, car dans l’interface il y a un espace de 6px entre deux éléments du menu.
Ensuite nous masquons les fameux spans des , ce qui permet ainsi de ne pas avoir de texte par-dessus les images de fond que nous allons mettre dans les liens. Les lignes suivantes mettent les images de fond en question dans chacun des 7 menus, en empêchant leur éventuelle répétition. Un rollover est aussi possible :

#menu a.menu7:hover { background:url("menu7-hover.gif") no-repeat; }

Conclusion

Notre interface est maintenant terminée. Vous pouvez en voir la version définitive. La même technique est applicable pour des interfaces plus compliquées. J’ai ici évité autant que possible les différences IE/W3C en évitant de définir ensemble largeur et marges internes, car IE ne gère pas par défaut le même système de mesures…