Tutoriel HTML & CSS

Par Sébastien Laoût
Version 0.3

Nous avons maintenant fait le tour du HTML et du CSS, la théorie n'a plus de secret pour vous, et vous avez une meilleure idée de ce qu'il est possible de faire avec ces technologies.
Nous allons maintenant mettre en pratique ces connaissances pour réaliser un site internet de A à Z.
Nous partirons d'une maquette HTML du site, avec tous les éléments habituels : un en-tête et un pied de page, un menu, plusieurs colonnes, des boutons, des titres, sous-titres et liens. Puis nous stylerons cette maquette à l'aide du CSS.
Cette maquette se veut fidèle à vos attentes concernant vos futurs projets de sites. Vous pourrez ainsi la reprendre en tant que base pour vos sites.

Présentation

Pour la réalisation de notre maquette graphique de site, quoi de plus opportun que la réalisation d'un site pour une société de vente de maquettes. Nous allons réaliser une maquette de site de maquettes, en quelque sorte. Dans un grand élan d'inspiration, nous appellerons la société "Maquettes Casey Steven & Son" !

Nous allons réaliser une page assez typique, avec un entête visuel contenant le titre du site et prenant toute la largeur de l'écran en haut de celui-ci. Un pied de page similaire sera présent en bas de l'écran et affichera une ou deux lignes de textes légaux, tels que le copyright, et un lien de contact, ou autres informations utiles.

Tout site se respectant dispose bien-sûr d'un menu. Notre maquette en contiendra donc. Par contre, il existe deux façon de présenter un menu de site : horizontalement en haut de l'écran sous l'entête, ou verticalement, avec une colonne à gauche ou à droite de l'écran. Afin d'être exhaustifs, nous allons voir les deux types de menus, qui se construisent légèrement différemment en CSS. Nous prétexterons alors avoir besoin de deux menus :

En temps normal, vous n'aurez besoin que d'un menu. Vous n'aurez qu'à garder celui du type que vous souhaitez pour votre site.

Afin d'avoir une vision globale tout au long de ces chapitres, voici le résultat global que nous souhaitons obtenir :

Le résultat final de la maquette de site que nous souhaitons réaliser

Aperçu de la fenêtre de la maquette modifiable

La maquette modifiable
À tout moment, vous pouvez vous référer à cette maquette modifiable afin de mieux appréhender l'étendue des modifications que nous allons faire en CSS. Je serais même tenté de vous imposer d'ouvrir cette fenêtre et d'activer et désactiver les lignes du CSS au fur et à mesure qu'elles vous sont expliquées ci-dessous. Vous comprendrez ainsi mieux le but de chaque propriété CSS utilisée. N'hésitez-pas à tester le plus de combinaisons possibles. Enfin, cette maquette vous permet de visualiser le code HTML et le code CSS dans son entier, vous permettant d'avoir une vision globale.

Voici les images dont nous avons besoin. Certaines vous sembleront bizarres, telles que menu-lien.png, mais nous allons tout expliquer plus bas :

body.png entete.png h1.png

menu.png menu-lien.png menu-lien-droite.png

pied.png sous-menu.png sous-menu-lien.png

Enfin, sachez que toutes les images, fichiers HTML et CSS... seront téléchargeables à la fin de cette partie. Pas la peine de télécharger toutes les images ci-dessus une par une ;-) Vous aurez même droit au fichier SVG source afin que vous puissiez les modifier.

Avant de commencer la lecture, et pour vous donner l'envie d'apprendre,
Découvrez Snaky 360, le jeu de serpent addictif réalisé par l'auteur de ce tutoriel...

Créé entièrement en HTML, CSS et JavaScript, sans Flash
(sauf pour les musiques et effets sonores, en attendant HTML 5)
Bientôt, vous pourrez en faire de même !

Ou alors, jouez à sa version Android :
Disponible sur le Play Store

Pendant qu'on y est, je peux aussi vous présenter la carte du monde que j'ai réalisé :
en très grand format pour vos murs, au design naturel et artistique :

La page

Nous allons commencer par présenter le fichier HTML de base :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="fr">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Catalogue des bateaux - Maquettes Casey Steven &amp; Son</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <!--[if lt IE 8]><link rel="stylesheet" type="text/css" href="ie.css"><![endif]-->
  </head>
  <body>
    Le contenu de la page viendra ici.
  </body>
</html>

Notez que la balise <body> est vide pour le moment. Nous allons la remplir au fur et à mesure plus bas. Voyons tout d'abord cette portion brique par brique. Les premières lignes vous semblent familières :

Passons maintenant à la mise en forme avec du CSS de la page dans sa totalité. C'est la partie la plus simple. Il s'agit ici de définir une marge respectable pour que le vrai contenu de la page soit espacé de la bordure du navigateur, pour un site plus clair et aéré. Pour rendre cette marge plus attrayante, nous allons appliquer une texture de fond en forme de grille grise et blanche. Finalement, la majorité des navigateurs utilisent une police de caractères avec empâtements (du type Times New Roman). Afin de donner au site un aspect plus moderne, nous définissons une police de caractères sans empâtements (sans-serif). Nous plaçons tout ceci dans la balise body, qui est le support de la page. Il en va de même avec la police de caractères, qui sera ainsi héritée par toutes les balises filles de body. Autrement-dit, par toutes les balises !

body.png

body {
  background: #eaeaea url('images/body.png'); /* (grille grise et blanche) */
  margin: 20px 30px; /* Donner plus de marge à gauche et à droite, et moins en haut et en bas */
  font-family: sans-serif; /* Police moderne, sans empattements, du type Times New Roman */
}

Rappel sur la syntaxe courte des propriétés CSS :
La ligne CSS background: #eaeaea url('images/body.png'); regroupe en fait deux propriétés liées au fond, et est à peu près équivalente à background-color: #eaeaea; background-image: url('images/body.png');. "À peu près", car les propriétés background-position, background-reapeat, etc. sont remises à zéro du fait de l'utilisation de la propriété courte background.

La ligne CSS margin: 20px 30px; définit une marge haute et basse de 20 pixels et une marge gauche et droite de 30 pixels. Celle ligne est équivalente à margin: 20px 30px 20px 30px;, qui définit, dans cet ordre : les bordures haute, droite, basse puis gauche. Elle est donc exactement équivalente à margin-top: 20px; margin-right: 30px; margin-bottom: 20px; margin-left: 30px;.

À vous de jouer :
Dans la maquette modifiable, je vous conseille de tout décocher (en cliquant sur le lien en haut à gauche de la fenêtre) puis de cocher les lignes au fur et à mesure que nous les expliquerons ici. En l'occurrence, décochez toutes les cases et re-cochez les 3 premières cases correspondantes à la règle body. Le résultat n'est pas bien spectaculaire, mais cela vous permet de prendre en main la maquette modifiable. Les encadrés "À vous de jouer" à suivre seront plus intéressants ;-)
Ouvrir la maquette modifiable

L'entête

À l'intérieur de la balise <body>, nous distinguons plusieurs blocs importants. Ces blocs sont généralement des balises <div> afin d'entourer le code en lui donnant une signification. Cette signification (ou sémantique) ne peut pas s'exprimer grâce à du HTML (il n'y a pas d'élément entête, pied de page, menus...). Ces blocs importants sont nommés avec des IDs afin de pouvoir leur appliquer un style avec du CSS. Vous pouvez très bien utiliser des classes si vous voulez, mais ces éléments étant uniques dans la page, utiliser des IDs est un peu plus logique.

L'entête visuel de la page est constitué de ce code HTML, à placer dans la balise <body> du code HTML précédent :

    <div id="entete">
      <h1>Maquettes Casey Steven &amp; Son</h1>
      Le menu principal viendra ici.
    </div>
    Le reste de la page viendra ici.

L'entête visuel de la page est le div avec l'id "entete". Il contient le titre du site h1 et le menu principal. Ces deux blocs, de part leur hauteur, vont forcer la hauteur du bloc "entete". Pas besoin, donc, de définir une hauteur pour le bloc entete. Tout ce que nous avons à définir est l'image de fond. C'est celle présente ci-dessous, et elle sera répétée afin de former une barre grise complète. Comme nous l'avons défini, le fond apparaîtra également sous le menu principal, mais ce n'est pas grave, car ce menu aura sa propre image de fond qui couvrira la répétition non-voulue de l'image de fond de l'entête. Vous allez me dire : mais alors, pourquoi ne pas assigner l'image de fond au h1, puisque qu'elle ne sera visible que sous le titre de la page. Et bien nous allons le voir dans un instant : nous allons assigner le logo de l'entreprise comme image de fond au titre h1. Et un élément ne peut avoir qu'une seule image de fond (ce ne sera plus vrai lorsque le CSS3 pourra être utilisé). Nous rusons donc en déportant la "seconde image de fond du titre" dans le bloc de niveau supérieur.

entete.png

Nous définissons également une bordure noire de un pixel tout sur tous les bords du bloc, sauf le bord du bas. Pourquoi ? Car le moment venu, nous définiront également une bordure noire de un pixel sur le bloc page. Les deux blocs étant l'un au dessus de l'autre, deux bordures seraient ajoutées, ce que nous ne voulons pas.

#entete {
  background: #9f9f9f url('images/entete.png'); /* (grosse barre grise) */
  border: 1px solid black; /* Une bordure noire de 1 pixel sur tous les côtés, sauf... */
  border-bottom: none; /* ... en bas, pour ne pas faire double-emploi avec la bordure du haut de #page */
}

Rappel sur la syntaxe courte des bordures :
La ligne CSS border: 1px solid black; est la forme courte pour : border-width: 1px; border-style: solid; border-color: black;. Les trois propriétés sont nécessaires pour faire apparaitre la bordure. On ne peut pas donner une couleur à la bordure sans spécifier sa taille, ni même sa forme (pleine, en pointillés...). La forme courte est donc assez intéressante, car vous aurez souvent besoin de définir des bordures sans trop alourdir le code CSS.

Ici, nous désirons une bordure en haut, à droite et à gauche, mais pas en bas. Nous définissons une bordure générale, puis redéfinissons la bordure basse comme inexistante. Cela aurait pu être fait en définissant uniquement les trois bordures, au risque de produire du code redondant (et devant donc être modifié à plusieurs endroits si vous changez d'avis sur le style) : border-top: 1px solid black; border-right: 1px solid black; border-left: 1px solid black;.


Passons maintenant au style du titre H1.

Nous définissons sa hauteur à 58 pixels, ce qui est la hauteur de la barre grise de entete.png. Nous définissons également line-height à cette valeur. Cette propriété représente la hauteur de chaque ligne du bloc h1, en l'occurrence il n'y a qu'une ligne. En effet, la hauteur des lignes dépend de la taille de la police de caractères, mais elle est habituellement différente de la taille de la police de caractères, afin que chaque ligne d'un texte soit assez espacée de la suivante. Nous devons donc contrôler cette hauteur afin d'avoir le design que nous souhaitions. Cette propriété a également l'effet de centrer verticalement le texte sur les lignes. Ce centrage est le comportement par défaut : vous pouvez demander à ce que le texte soit aligné sur le bas ou sur le haut des lignes, ce qui n'est pas notre cas. Ainsi, le titre est maintenant verticalement centré sur la barre grise.

Il ne reste plus qu'à le centrer horizontalement grâce à la propriété "text-align" avec la valeur "center".

Ensuite, un titre normal doit être espacé des autres sous-titres et paragraphes, donc les navigateurs dotent les titres et paragraphes de marges par défaut. Nous n'en voulons pas ici, nous remettons donc la marge du titre h1 à zéro.

Enfin, nous séparons le titre du menu qui va suivre par une bordure noire :

h1 {
  height: 58px; /* La hauteur de entete.png (grosse barre grise) */
  line-height: 58px; /* Centrer le texte sur toute la hauteur de l'image de fond */
  border-bottom: 1px solid black; /* L'entête est composé de deux parties : h1 et #menu, il faut donc les séparer */
  margin: 0; /* Par défaut les navigateurs assignent une marge aux titres. Ici on gère notre propre mise en page */
  text-align: center; /* Centrer le texte horizontalement sur toute la largeur de la page */

Nous allons maintenant voir une technique CSS assez intéressante : elle permet de remplacer le texte assez triste par une image plus agréable et correspondant à la charte graphique de l'entreprise. Voici l'image qui va remplacer le texte. Il s'agit du logo de l'entreprise :

h1.png

Oui, le logo de la société a plus l'air d'être un titre de dessin animé, mais ce logo a été créé rapidement :-)

Pourquoi ne pas placer une image directement dans le fichier HTML ?
Afin que l'image puisse être changée en un seul endroit si vous souhaitez appliquer, par exemple, un thème différent à noël, un autre pour Halloween, etc. Mais surtout pour vous exposer cette technique qui est assez intéressantes dans certains autres cas. Il est vrai que dans le cas de ce logo d'entreprise qui ne changera jamais, il aurait été plus judicieux d'utiliser une balise <img> dans le <h1> et de définir le texte dans l'attribut title du tag img. Ainsi, lorsque l'image n'est pas encore chargée, le texte de l'attribut title est affiché en clair à la place.

Cette technique consiste en deux étapes. Tout d'abord, il faut afficher l'image (le logo). Nous ne pouvons faire cela en CSS qu'avec la propriété background. L'image sera affichée une seule fois (no-repeat) et centrée au milieu du bloc (50% 50%).

Pour cacher le texte, nous utilisons la propriété text-indent, qui permet d'indenter le texte. Elle est différente du padding, car un padding ne peut pas être négatif (au contraire de margin). Nous déplaçons donc le texte de 32 000 pixels vers la gauche. Les décalages vers la gauche ou vers le haut ne résultent jamais en l'apparition de barres de défilement, ce qui nous arrange car nous souhaitons cacher le texte et le rendre inaccessible. La valeur 32 000 pixels est relativement grande pour être certain qu'aucune partie du texte ne soit visible, tout en restant dans la gamme des valeurs permises par les navigateurs.

  background: url('images/h1.png') 50% 50% no-repeat; /* Cette jolie image, unique et centrée, remplace le texte ennuyeux */
  text-indent: -32000px; /* On décale le titre autant que possible sur la gauche de l'écran, pour ne plus le voir */
}

Les portes coulissantes

Si vous le voulez bien, nous allons abandonner la maquette quelques instants afin de vous montrer deux techniques qui nous seront utiles pour continuer la maquette.

La technique des portes coulissantes est très utile en CSS. Elle nous permettra de réaliser les boutons du menu principal. Elle permet également de réaliser des boutons aux bords arrondis, des onglets, etc. qui s'adaptent à la largeur ou la hauteur du bouton ou de l'onglet. Elle permet aussi de réaliser une ombre pour des blocs, et plus généralement de réaliser toutes sortes de blocs graphiques.

Commençons pour montrer le résultat que nous voulons atteindre. Notre site a besoin de plusieurs boutons aux coins arrondis. Nous voulons quatre boutons dans cet exemple, et nous voulons que ces boutons s'adaptent à la largeur du texte qu'ils contiennent. Nous allons voir comment réaliser ceci en CSS, en n'utilisant que deux images. Voici sans plus tarder le résultat :

Premier bouton
Bouton plus grand
Un bouton encore plus grand
Soyons fous, et créons ce bouton dééééééémesuré

Voici les deux seules images dont nous avons besoin :

bouton-gauche.png bouton-droite.png

Et le code HTML d'un bouton :

<div class="bouton"><div>Texte du bouton</div></div>

Comme vous pouvez l'imaginer de part ces deux images et le nom de la technique, nous allons faire coulisser la seconde sur la première. Le secret de la technique réside dans les deux div imbriqués, nous permettant d'appliquer deux images de fond au bouton : une très longue à gauche, correspondant au bord gauche du bouton ainsi qu'à son contenu, et une petite à droite, correspondant au bord droit du bouton.

Voici une petite illustration montrant le bloc parent et le <div> imbriqué légèrement décalés, puis rapprochés progressivement jusqu'à arriver au résultat final, où les deux blocs se superposent parfaitement. La bordure noire est présente pour délimiter les deux blocs, et la partie semi-transparente indique qu'image-gauche.png continue, mais est invisible, car en dehors du bloc. On voit très bien que les bords arrondis ne sont pas transparents, mais blancs, pour cacher l'image du dessous :

Illustration montrant comment le bloc imbriqué s'emboite visuellement dans son parent pour former une image de bouton

Le code CSS est le suivant :

.bouton {
  background: url('images/bouton-gauche.png'); /* Bord gauche et contenu du bouton */
  float: left; /* Afin que le DIV prenne la largeur de son contenu, et non la largeur de la page, pour des raisons didactiques */
  margin: 7px; /* Espacer les boutons entre eux, rien à voir avec la technique des portes coulissantes */
}

.bouton div {
  background: url('images/bouton-droite.png') 100% 0 no-repeat; /* Bord droit du bouton, aligné à droite ! */
  height: 30px; /* Hauteur des images bouton-gauche.png et bouton-droite.png */
  line-height: 30px; /* Centrer le texte verticalement sur le bouton */
  padding: 0 10px; /* S'assurer que le texte ne soit pas collé aux bordures du bouton */
  color: white; /* Le bouton est bleu foncé, le texte doit être clair */
}

Quelques explications. D'abord, les deux images de fond son assez évidentes. Il faut toutefois s'assurer que celle de gauche soit aussi longue que le plus long des boutons que vous voulez créer. Dans le cas contraire, vous risquez d'obtenir le résultat suivant :

Un bouton non prévu, car bien plus long que l'image bouton-gauche.png, ce qui fait boguer le CSS !

Ceci est donc à prévoir en créant l'image de fond. L'image de droite doit être alignée à droite (background-position: 100% 0), et affichée une seule fois, d'où le no-repeat. Celle de droite doit également avoir un fond de couleur unie. Le bouton a des bords arrondis, mais ces bords ne peuvent pas être transparents, car ils laisseraient voir l'image bouton-gauche.png qui se trouve en dessous. L'image bouton-droite.png doit être entièrement opaque pour couvrir celle de gauche. Ici, les coins sont d'un blanc uni, couleur de fond de la page.

Le reste du code CSS est là pour s'assurer que les boutons auront une hauteur fixe de 30 pixels, la hauteur des images. Pour les besoins de l'exemple, les boutons doivent être espacés, d'où la marge de 7 pixels. Et le texte des boutons ne doit pas coller aux bordures des boutons, nous ajoutons donc un espacement intérieur horizontal de 10 pixels, la largeur des coins arrondis des images (padding: 0 10px).

Enfin, les balises <div> prenant par défaut toute la largeur de la page et apparaissant les unes en dessous des autres (ce sont des balises bloc), nous utilisons la propriété float: left, afin que les div adoptent la largeur de leur contenus et se placent les uns à côté des autres. Il ne faut donc pas oublier de faire suivre ces boutons d'un bloc ayant la propriété CSS "clear: left;" ou "clear: both;" afin de le positionner après les boutons, et non au dessus.

Rappel sur la taille des éléments :
Nous avons ici utilisé des éléments blocs et avons du utiliser la propriété float afin que leur largeur soit automatiquement adaptée au contenu. Pourquoi ne pas avoir utilisé des éléments en ligne, tels que des balises <span> ? Car nous avons besoin d'assigner une hauteur de 30 pixels aux boutons.
Hors, un élément en ligne ne peut pas se voir attribuer une taille, alors qu'un élément bloc peut se voir attribuer une largeur et une hauteur.

Ces boutons ne sont pas cliquables, car ils n'ont pour but que d'expliquer la technique des portes coulissantes. Pour les rendre cliquables, remplacez le premier <div> par un lien (balise <a>) auquel vous attribuerez le CSS "display: block;" afin qu'il se comporte comme un <div>. Un lien ne pouvant pas contenir de balise bloc, il faut remplacer le <div> intérieur par une balise el ligne <span>. Vous attribuerez la même propriété CSS "display: block;" afin de pouvoir lui assigner une taille.


La technique des portes coulissantes sert également à réaliser des blocs aux bords arrondis ou des blocs avec une ombre. Ces blocs pouvant être de n'importe quelle taille. En guise de second exemple, nous allons réaliser les deux à la fois : des blocs à bords arrondis et avec une ombre, dont en voici quelques uns :

Un bloc de 100 pixels de largeur.
Un bloc de 300 pixels de largeur.
Un bloc de 400 pixels de largeur avec beaucoup de texte très technique à l'intérieur :
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc metus. Aliquam elementum euismod massa. Suspendisse potenti. Maecenas laoreet. Nulla volutpat nisl eget est. Quisque lorem augue, iaculis eu, pellentesque sit amet, dictum tincidunt, mi. Curabitur vitae ipsum.

Comme tout à l'heure, voici les images composant ce cadre. Elles sont au nombre de quatre, car nous permettons au cadre d'avoir une largeur et une hauteur variable :

cadre-haut-gauche.png cadre-droite.png

cadre-bas.png cadre-bas-droite.png

Notez bien que nous avons minimisé le nombre de fichiers. Il en aurait fallu huit : quatre pour peindre les quatre coins et quatre autres pour les bords. Ici, cadre-haut-gauche.png comporte le coin haut-gauche et les bordures haute et gauche, cadre-droite.png comprends également le coin haut-droit, et cadre-bas.png contient aussi le coin bas-gauche. Ces images ont été taillées pour un bloc de maximum de 500 par 200 pixels.

Si vous souhaitez ne faire qu'une ombre (pour rehausser une image, par exemple), vous n'avez besoin que de trois fichiers. L'image cadre-haut-gauche.png est alors superflue, et les trois autres sont modifiées pour ne contenir que l'ombre.

Le code HTML d'un cadre est le suivant :

<div class="boite" style="width: 300px;">
  <div>
    <div>
      <div>
        Texte du cadre de 300 pixels
      </div>
    </div>
  </div>
</div>

Oui, il y a bien quatre <div> imbriqués, un <div> par image de fond à appliquer. Ces balises HTML paraissent inutiles, et vont à l'encontre de la séparation du contenu et de la forme, mais elles sont nécessaires pour le moment. En CSS 3, il sera possible d'appliquer plusieurs images de fond à chaque balise, ce qui simplifiera le code HTML. Le code CSS sera quant à lui légèrement différent, mais la technique restera la même. Une autre possibilité qui sera offerte par le CSS 3 pour résoudre ce problème sera les images-bordures.

À partir des quatre images, du code HTML et de l'exemple précédent, vous devriez être capable de deviner quel sera le code CSS associé.

Je vous laisse donc réfléchir au code CSS.

Ça y est ?

Si vous avez joué le jeu, vous ne devez lire les paragraphes suivants que pour vérifier que votre solution est bonne.

Voici donc la solution :

.boite {
  background: #f0f0f0 url('images/cadre-haut-gauche.png'); /* La couleur de fond de la boite... */
  margin: 7px; /* ... ainsi que la marge de la boite se définissent dans le bloc le plus externe */
}

.boite div {
  background: url('images/cadre-bas.png') 0 100% no-repeat;
}

.boite div div {
  background: url('images/cadre-droite.png') 100% 0 no-repeat;
}

.boite div div div {
  background: url('images/cadre-bas-droite.png') 100% 100% no-repeat;
  padding: 13px 16px 16px 13px; /* L'espacement intérieur de la boite se définit dans le bloc le plus interne */
}

/* Petit bonus de sécurité : */
.boite div div div div {
  background: none; /* Si la boite contient elle-même des div, éviter que ceux-ci aient cadre-bas-droite.png comme image de fond... */
  padding: 0;       /* ... et qu'elles aient un padding, définit dans la règle ci-dessus */
}

Les quatre images sont assignées aux quatre blocs <div>, en faisant attention à leur ordre, les plus petites devant être au dessus des plus grandes pour les recouvrir. Si les images de fond ne sont pas chargées, on veille à mettre une couleur de fond au bloc. Cette couleur devant être en dessous de toutes les images, elle est obligatoirement placée dans le bloc le plus externe. Idem pour la marge du cadre tout entier : les quatre <div> devant être parfaitement alignés, la marge est assignée au bloc le plus externe. Au contraire, le padding doit être assigné au bloc le plus interne, sinon les blocs ne seraient plus alignés. Nous voulons 10 pixels de padding, mais il faut y rajouter 3 pixels pour la bordure (total : 13 pixels), et 3 pixels pour l'ombre sur les bords droit et bas (total : 16 pixels pour ces bords).

Pour revenir aux boutons, nous verrons comment effectuer un effet graphique lors du survol des boutons par la souris. Nous avons d'abord besoin de voir la technique suivante. Puis, nous combinerons les deux techniques afin de réaliser le menu principal.

Effet au survol de la souris

Voici une seconde technique très utilisée en CSS. Elle permet de changer l'image de fond d'un bouton sans clignotement.

La méthode la plus simple d'obtenir un effet graphique au survol de la souris est la suivante :

a {
  background: blue url('images/bouton-bleu.png');
}

a:hover {
  background: yellow url('images/bouton-jaune.png'); /* Ceci est la MAUVAISE méthode, qui fait clignoter les liens */
}

Cette méthode a un gros inconvénient : l'image bouton-jaune.png n'est chargée que lorsque le visiteur passe sa souris sur un lien. Lorsqu'il fait ceci, l'image bleue disparait et le navigateur commence à charger l'image jaune. L'image jaune apparaîtra un instant plus tard, ou quelques secondes plus tard, si l'image est grande, si le serveur est encombré, ou si le visiteur n'a pas une très bonne connexion. Durant le temps de chargement, le bouton n'a plus d'image de fond. Cette méthode fait donc clignoter des liens, ce qui est désagréable pour le visiteur.

Afin de s'assurer que l'image jaune soit pré-chargée avec le chargement de la page, certains utilisent du JavaScript. Cette méthode est contraignante, car vous devez faire en sorte de charger chaque images. Si le code CSS change, il faudra modifier le code JavaScript correspondant, ce code pouvant être à modifier dans chaque page HTML.

C'est ici qu'intervient la méthode des sprites. Elle consiste à réunir les deux images (normale et survolée) dans une seule image, l'une en dessous de l'autre, ou l'une à côté de l'autre, en fonction des besoins. Ainsi, le navigateur n'a qu'une seule image à charger. Seule la partie normale sera visible en temps... normal. Et au moment du survol de la souris, nous décalons l'image afin de faire apparaître la zone qui représente le bouton survolé. L'image restant la même, elle est déjà en mémoire sur l'ordinateur du visiteur et le changement est instantané.

Nous allons reprendre l'exemple du bouton vu plus haut. Le code HTML a été modifié pour prendre en compte la remarque que nous avons émise tout à l'heure, à savoir que le bouton est maintenant cliquable car nous avons remplacé les deux <div> par un lien <a> et une balise en ligne <span> :

<a href="#survol" class="bouton"><span>Texte du bouton</span></a>

Ces modifications ne sont pas très importantes pour cette technique. Le plus important est que les deux images changent pour devenir celles-ci :

bouton-gauche.png bouton-droite.png

Il y a bien deux images, et non quatre. Les parties du haut représentent un bouton dans l'état normal, et les parties du bas représentent un bouton survolé. Voici un schéma illustrant le principe de la technique :

Illustration montrant un bouton à l'état normal, puis survolé, avec la position des images de fond des deux blocs imbriqués

Voici la première partie du code CSS :

.bouton {
  background: url('images/bouton-gauche.png'); /* Bord gauche et contenu du bouton */
  float: left; /* Afin que le DIV prenne la largeur de son contenu, et non la largeur de la page, pour des raisons didactiques */
  margin: 7px; /* Espacer les boutons entre eux, rien à voir avec la technique des portes coulissantes */

  /* Ce qui change par rapport à l'exemple précédent : */
  display: block; /* Pour pouvoir assigner une taille */
  text-decoration: none; /* On utilise un lien au lieu d'un div. Un lien est souligné par défaut, mais on veut le même look qu'avant */
  cursor: pointer; /* Curseur en forme de main, pour résoudre un bug sous IE, causé lors du changement du lien en affichage bloc, quelques lignes plus haut */
}

.bouton span {
  background: url('images/bouton-droite.png') 100% 0 no-repeat; /* Bord droit du bouton, aligné à droite ! */
  height: 30px; /* Hauteur des images bouton-gauche.png et bouton-droite.png */
  line-height: 30px; /* Centrer le texte verticalement sur le bouton */
  padding: 0 10px; /* S'assurer que le texte ne soit pas collé aux bordures du bouton */
  color: white; /* Le bouton est bleu foncé, le texte doit être clair */

  /* Ce qui change par rapport à l'exemple précédent : */
  display: block; /* Pour pouvoir assigner une taille */
}

Dans cette première partie, le code ne change pas énormément par rapport aux boutons utilisant la technique des portes coulissantes. Vu que nous avons remplacé les deux <div> par un <a> et un <span>, nous devons faire en sorte que ces deux balises se comportent comme des balises blocs <div>, et en enlevant le soulignement par défaut des liens. Notez que vous Internet Explorer, assigner la propriété "display: block;" à un lien lui fait perdre son curseur en forme de main ! Ce bug sera peut-être résolu dans la version 8... Mais pour le moment, nous utilisons "cursor: pointer;" afin de corriger ce bug dès maintenant.

Et voici la seconde partie du code CSS, qui implémente la technique des sprites pour réaliser les effets au survol de la souris :

.bouton:hover,
.bouton:focus,
.bouton:active {
  background-color: yellow; /* On n'utilise pas la forme courte "background: ...;" car on devrait alors re-spécifier l'URL vers l'image */
  background-position: 0 -30px; /* On remonte l'image de 30 pixels (la moitié de sa hauteur) pour voir la partie jaune */
}

.bouton:hover span,
.bouton:focus span,
.bouton:active span {
  background-position: 100% -30px; /* Toujours aligné à droite, mais remonté de 30 pixels (la moitié de sa hauteur) pour voir la partie jaune */
  color: black; /* Le fond devient jaune, donc le texte doit être noir pour être visible */
}

Lors du survol de la souris, les deux images de fond sont remontées de 30 pixels afin de révéler les parties orange. Il est à noter qu'il n'est pas possible de modifier la position en y des images de fond sans changer sa position x. C'est pourquoi nous définissons deux chiffres : "0 -30px" pour remonter l'image du lien tout en le laissant aligné à gauche, et "100% -30%" pour le span afin de remonter l'image en la laissant alignée à droite. Nous changeons également la couleur de fond du bouton. Ainsi, si les images n'ont pas pu être chargées (connexion interrompue, sauvegarde de la page sans ses images...), il y a tout de même un effet.

Remarquez qu'ici, nous n'avons pas utilisé la propriété courte "background" pour définir les deux propriétés background-color et background-position. Car, dans ce cas, il aurait également fallu redéfinir la propriété background-image, ce qui aurait produit un code redondant. Une modification futur du nom de l'image aurait alors nécessité de modifier le code CSS en deux endroits.

Effets au focus par le clavier (:focus et :active) :
Vous aurez remarqué qu'en plus des deux règles ":hover", ces deux règles sont dupliquées en remplaçant ":hover" par ":focus" et ":active". Ces lignes sont facultatives, mais sont toujours les bienvenues, pour les personnes naviguant sur votre site au clavier. En effet, ces personnes utilisent la touche Tabulation pour mettre le focus (activer) sur le lien ou le champs suivant, Maj+Tabulation pour le lien ou champs précédent, et Entrée pour suivre le lien ayant actuellement le focus (étant actuellement actif, et généralement encadré en pointillés).

La règle ":focus" permet d'assigner un style particulier à l'élément (lien ou champs de formulaire) ayant le focus. La règle ":active" permet d'assigner un style particulier au lien que l'on est en train de cliquer. Enfin, Internet Explorer n'interprète pas la règle ":focus", mais utilise la règle ":active" comme s'il s'agissait de ":focus". C'est pour cela que l'on définit à la fois ":focus" et ":active". Et ":hover" complète le trio, pour que les utilisateurs navigants au clavier ou à la souris aient la même expérience du site.

Afin de tester ce style, cliquez droit sur le premier bouton de l'exemple ci-dessous, ce qui aura pour rôle de mettre le focus sur le bouton. Puis, appuyez immédiatement sur Échap afin de fermer le menu. Pressez Tabulation deux ou trois fois pour naviguer entre les boutons. Vous pouvez constater que le bouton actif a le même style qu'un bouton survolé par la souris.

Enfin, voici le résultat obtenu. Passez votre souris sur les boutons pour voir que l'effet ne souffre d'aucun clignotement désagréable :

Le menu principal

Voici le code HTML à placer juste en dessous de la balise <h1>. Le menu aurait très bien pu être positionné juste après l'entête, c'est vous qui voyez. Ici, nous considérons que c'est un élément qui fait partie de l'entête de la page, car il est en haut de toutes les pages.

      <ul id="menu">
        <li><a href="#"><span>Lien 1</span></a></li>
        <li><a href="#" class="actuel"><span>Lien 2</span></a></li>
        ...
      </ul>

Oui, le menu est disposé sous forme de liste <ul> dont chaque ligne <li> contient des liens <a> car, après tout, un menu ou une barre de navigation ne sont rien d'autre que des listes de liens ! Le CSS va permettre de changer la forme visuelle de cette liste pour qu'elle ressemble à une barre de navigation ! Nous verrons plus tard que le sous-menu vertical a la même structure HTML que le menu principal. Grâce à leur id différent, nous pouvons leur appliquer un style différent.

Rappel sur la propriété float :
L'utilisation de la propriété "float: left;" et "float: right;" permet d'extraire un bloc du flux normal de la page, et de le "faire flotter" sur la gauche ou la droite de l'élément parent. Les autres blocs conservent leur position "en-dessous des blocs flottants", comme s'ils n'existaient pas, mais le texte de ces autres blocs est tout de même décalé de façon à ne pas apparaître sur les éléments "flottants".

Pour le menu principal, nous aurons besoin de ces trois fichiers :

menu.png menu-lien.png menu-lien-droite.png

Voyons maintenant le code CSS, que nous découperons en trois parties pour en faciliter l'explication :

#menu {
  background: black url('images/menu.png'); /* (barre noire, avec un bandeau à rayures noir et orange juste en dessous) */
  list-style: none; /* On ne veut plus que les lignes de la liste aient de puces */
  margin: 0; /* Aucune marge au dessus et en dessous de la liste (les listes étant normalement utilisées entre des paragraphes) */
  padding: 0; /* Aucune indentation des éléments contenus dans la liste (généralement, les listes ont un padding à gauche) */
  height: 29px; /* Hauteur de l'image menu.png */
}

#menu li {
  float: left; /* Afin que chaque élément de la liste se positionne juste à droite de l'élément précédent, et non en dessous */
  margin: 0 2px; /* Espacer horizontalement chaque bouton à l'intérieur du menu */
}

La première étape est de faire en sorte que la liste ne ressemble plus à une liste, mais à une barre de navigation horizontale. Pour cela :

Le reste de la règle #menu est assez basique : on définit une image de fond, ainsi qu'une couleur de fond noire (au cas où l'image de fond ne soit pas chargée).

#menu a {
  display: block; /* Afin de pouvoir assigner une hauteur au lien (la hauteur étant définir dans la règle "#menu span") */
  text-decoration: none; /* Pas de soulignement des liens dans le menu, ils sont déjà identifiables en tant que liens par le visiteur */
  color: #ffb400; /* Le texte est orange */
  background: url('images/menu-lien.png'); /* Bande noir, mais devenant orange lorsque décalée vers le haut */
  cursor: pointer; /* Curseur en forme de main, pour résoudre un bug sous IE, causé lors du changement du lien en affichage bloc, quelques lignes plus haut */
}

#menu span { /* Ce span permet au menu survolé d'avoir un reflet de lumière sur sa droite */
  display: block; /* Afin de pouvoir assigner une hauteur à cet élément (voir ci-dessous) */
  height: 21px; /* Hauteur de l'image menu-lien.png, divisé par 2 */
  line-height: 21px; /* Centrer le texte verticalement sur la barre noire */
  padding: 0 10px; /* Espacement intérieur du bouton à gauche et à droite, pour plus d'aération */
  background: url('images/menu-lien-droite.png') 100% 0 no-repeat; /* Une seule occurrence de l'image de fond, et aligné tout à droite */
}

Ces deux règles ne sont qu'une simple combinaison de la méthode des portes coulissantes (les deux propriétés "background: ...") et de la méthode des sprites pour un effet au survol de la souris vues plus haut, tout en reprenant l'astuce "display: block;" vu dans l'exemple précédent concernant les boutons bleus et orange.

Le reste n'est que pur décoration simplistes : couleur orange, aucun soulignement, définition d'un espacement entre les liens, et de la hauteur du menu. À noter que nous utilisons les propriétés height et line-height à l'intérieur de la balise span, et pas de la balise a.

#menu a:hover, /* Au survol de la souris */
#menu a:focus, /* Lorsque le lien a le focus, sous Firefox et autres navigateurs */
#menu a:active /* Lorsque le lien a le focus, sous Internet Explorer */
{
  color: black; /* Le fond devient orange, donc le texte doit être noir pour être visible */
  background-color: #ffb400; /* L'image de fond reste inchangée, mais si l'image n'a pas été chargée, s'assurer qu'il y ait un effet visible */
  background-position: 0 -21px; /* =42 (la hauteur de l'image) / 2 : remonte l'image de fond de moitié vers le haut pour révéler sa partie orange */
}

#menu a:hover span, /* Au survol de la souris */
#menu a:focus span, /* Lorsque le lien a le focus, sous Firefox et autres navigateurs */
#menu a:active span /* Lorsque le lien a le focus, sous Internet Explorer */
{
  background-position: 100% -21px; /* =42 (la hauteur de l'image) / 2 ; mais toujours aligné à droite */
}

#menu .actuel { /* Indique au visiteur que ce lien est en fait la page actuellement affichée */
  font-weight: bold; /* Gras... */
  text-decoration: underline; /* ... et souligné */
}

Deuxième partie de l'application de la méthode des sprites pour un effet au survol de la souris vues plus haut. Suivi d'embellissements de certains aspects, ce qui reste assez simple.

Comment se passer des éléments span ?
Vous l'aurez remarqué, les balises span sont présentes à l'encontre de la séparation du contenu et de la forme. Elles ne servent à rien sémantiquement, et ont été ajoutées ici afin de pouvoir appliquer cette feuille de style en particulier. C'est malheureusement une petite concession qu'il est parfois nécessaire à faire en CSS 2. Cela ne sera plus nécessaire en CSS 3, qui permettra d'assigner plusieurs images de fond par balise, ou de créer des balises parents ou enfants virtuelles en CSS...

Il n'empêche que les balises span de cet exemple sont inutiles, même en CSS 2. En effet, nous avons déjà deux balises imbriquées auxquelles ont peut appliquer les deux images de fond pour réaliser la technique des portes coulissantes. J'ai nommé les balises <li> et <a>. Il suffit de placer menu-lien.png dans la balise <li> au lieu de la balise <a>, de placer menu-lien-droite.png dans la balise <a> au lieu de <span>. Ensuite, il faut modifier les effets "#menu a:hover" et les placer dans "#menu li:hover". De même pour les effets "#menu a:hover span", il faut les placer dans "#menu li:hover a". On remonte les images et les effets d'une balise, respectivement. Je vous laisse supprimer les balises <span> et modifier le CSS en guise d'exercice, en vous modifiant les fichiers à télécharger en bas de cette page.

Si les balises <span> sont inutiles, alors pourquoi les avoir mises ici ? Il s'agit de reste compatible avec Internet Explorer 6 et précédents, même si cela sera de moins en moins nécessaire au fur et à mesure qu'Internet Explorer 7 et ses successeurs seront utilisés. Internet Explorer 6 et précédents ne permettent d'utiliser la pseudo-classe ":hover" uniquement sur les balises <a>. Donc la règle "a:hover" sera respectée, mais pas "li:hover" ! Comme nous avons besoin de changer deux images de fond imbriquées, il faut que la seconde balise soit à l'intérieur d'une balise <a> pour que cela fonctionne, d'où l'ajout de la balise span.

À vous de jouer :
Je vous conseille d'abord de décocher tout. Puis, cochez progressivement les lignes des règles "#menu" et "#menu li" afin de tester la première partie du code CSS. L'ordre des lignes a été étudié pour que vous voyiez effectivement des modifications à l'activation de chaque nouvelle ligne. Notez bien que sous Firefox, Opera, Safari... la ligne "margin: 0;" n'aura aucun effet et la ligne "padding: 0;" supprimera le décalage gauche de la liste. Sous Internet Explorer, c'est tout le contraire. En effet, ces navigateurs implémentent différemment l'indentation des listes et des sous-listes. Sous Internet Explorer, l'image de fond collera au texte, montrant qu'il n'y a aucun padding, alors que sur les autres navigateurs, l'image de fond sera proche de la bordue gauche de l'écran, ce qui démontre un padding non-nul et une marge nulle. Ce genre de détails est parfois très utile pour débuter une piste permettant de comprendre pourquoi un design CSS apparaît différemment dans les navigateurs. Vous pouvez ensuite décocher la ligne "height: 29px;" pour découvrir en quoi une ligne "clear: ..." n'est plus nécessaire.

Pour tester la troisième partie, passez votre souris sur les liens du menu après avoir activé chaque ligne afin de voir la modification qu'apporte chacune d'elles. Après cela, je vous suggère également de décocher les trois images de fond (simulant leur non chargement, pour voir l'effet qu'il y aura), de passer votre souris sur les liens, puis de re-cocher les images de fond en partant de la dernière, en passant votre souris sur les liens après chaque coche.
Ouvrir la maquette modifiable

Les colonnes

Afin de réaliser le sous-menu tout en respectant les principes des standards du Web, nous n'allons pas utiliser de tableau à deux colonnes et une ligne. En effet, les tableaux HTML (balise <table>) n'existent que pour présenter des données tabulaires, des statistiques, etc. Et en aucun cas pour mettre en forme la page. La technique que nous allons voir s'appel la techniques des colonnes factices. Pourquoi ? Elle consiste en ces quatre étapes :

  1. Les deux colonnes sont disposées à l'intérieur d'un bloc parent ;
  2. Nous décalerons les deux colonnes afin qu'elles ne se chevauchent pas visuellement : la colonne de gauche "flottera" à gauche, et la colonne de droite sera décalée vers la droite ;
  3. Le bloc parent contiendra une image de fond répétée verticalement pour simuler le fond de la colonne de gauche ;
  4. Le bloc de pied de page égalisera la hauteur des deux colonnes, grâce à la propriété clear.

Cela est très abstrait ! Rentrons donc dans le détail avec des explications plus compréhensibles.

1. Voici le code HTML du reste de la page, permettant de voir l'imbrication des blocs. Les parties non-relatives aux colonnes ont été réduites au minimum. Ainsi, le contenu du menu et du pied de page ne sont pas représentés ici, mais leur balise mère (ul et div) est présente afin de pouvoir les positionner en CSS :

    <div id="page">
      <ul id="sous-menu">Ici viendra le sous-menu.</ul>
      <div id="contenu">
        Placer ici le contenu effectif de la page : balises h2, h3, p, ul...
      </div>
      <div id="pied">Ici viendra le pied de page.</div>
    </div>

Le bloc "page" contient un sous-menu vertical placé sur la gauche de la page, puis le contenu de la page en lui-même (id="contenu") et enfin le pied de page. Ce pied de page est contenu à l'intérieur du div "page", et non en dehors, comme c'est le cas de l'entête, car nous en avons besoin pour cette technique.

Pour le moment, le code HTML ressemble à cela (des bordures ont été rajoutées afin de mieux visualiser les blocs) :

div#page
ul#sous-menu
...
div#contenu
...
...
...
...
...
div#pied

2. Afin de disposer le sous-menu à gauche du contenu, nous lui assignons la propriété "float: left;" :

div#page
ul#sous-menu
...
div#contenu
...
...
...
...
...
div#pied

Comme vous pouvez le voir, le sous-menu est plus petit que le contenu, donc dès qu'il y a suffisamment de place, les dernières lignes du div#contenu se placement en dessous du sous-menu. Pour remédier à cela et "simuler" le fait que nous avons deux colonnes, nous assignons une marge gauche de 200 pixels :

div#page
ul#sous-menu
...
div#contenu
...
...
...
...
...
div#pied

De manière similaire, nous fixons la largeur du sous-menu à 200 pixels :

div#page
ul#sous-menu
...
div#contenu
...
...
...
...
...
div#pied

3. Vient maintenant le moment de placer l'image de fond du menu. C'est celle ci :

sous-menu.png

Comme vous pouvez le voir, l'image ne peut pas être appliquée au sous-menu en lui-même, car il ne fait pas toute la hauteur de la page. Le CSS ne permet pas de définir la hauteur du sous-menu comme étant la hauteur du bloc parent. Seul le bloc parent div#page fait la hauteur de toute la page. C'est donc à lui que nous appliquons l'image de fond :

div#page
ul#sous-menu
...
div#contenu
...
...
...
...
...
div#pied

4. Tout semble terminé. Mais que ce passe-t-il si le menu est maintenant plus grand que le contenu ? Testons :

div#page
ul#sous-menu
...
...
...
...
div#contenu
...
...
div#pied

Et oui : le sous-menu est flottant, donc sa taille n'a plus aucune influence sur le flux de la page, et le pied est placé juste après le contenu. C'est donc pour cela que nous avons mis div#pied à l'intérieur de div#page, et nous à l'extérieur comme ce fut le cas pour l'entête. Il s'agit de rajouter la propriété "clear: both;" au pied de page pour que tout revienne dans l'ordre. Cette propriété indique de continuer le flux de la page après le dernier élément flottant. Donc le pied sera toujours positionné sous le sous-menu, et sous le contenu :

div#page
ul#sous-menu
...
...
...
...
div#contenu
...
...
div#pied

Il ne reste plus qu'un petit problème cosmétique : le pied de page a également l'image de fond noir de la colonne de gauche. Pas de problème, nous assignons au pied de page sa propre image de fond, qui cachera celle du menu. À supposer, bien sûr, que les blocs n'ont aucun espacement entre eux, ce qui n'est pas le cas pour cette démonstration :

div#page
ul#sous-menu
...
...
...
...
div#contenu
...
...
div#pied

En appliquant cette technique à la maquette du site, cela donne ce code CSS :

#page {
  background: white url('images/sous-menu.png') repeat-y; /* Technique des colonnes factices : le menu de gauche a un fond sur toute la hauteur de la page */
  border: 1px solid black; /* Encadrer toute la page par une bordure noire de 1 pixel */
}

#sous-menu {
  background: black url('images/sous-menu.png') repeat-y; /* Fond noir si images non chargées, mais il faut remettre l'image de fond de #page */
  float: left; /* Colonne de gauche sur la page */
  width: 198px; /* Largeur de l'image sous-menu-lien.png */
  list-style: none; /* On ne veut plus que les lignes de la liste aient de puces */
  margin: 0; /* Aucune marge au dessus et en dessous de la liste (les listes étant normalement utilisées entre des paragraphes) */
  padding: 0; /* Aucune indentation des éléments contenus dans la liste (généralement, les listes ont un padding à gauche) */
}

#contenu {
  margin: 10px 10px 10px 209px; /* 209px = 198px (largeur du menu) + 1 (bordure droite du menu) + 10 (la marge que l'on veut donner au contenu) */
}

#pied {
  clear: both; /* Si le menu de gauche est plus haut que le contenu de la page, s'assurer de positionner le pied juste en dessous du menu */
  background: #9f9f9f url('images/pied.png'); /* (bandeau à rayures noir et orange, avec une barre grise juste en dessous) */
  ...
}

Pas besoin d'expliquer ce code, car il a déjà été expliqué grâce à l'exemple des deux colonnes que nous venons de voir. Notez que quelques lignes de la règle "#sous-menu" seront utiles pour la partie suivante, mettant en forme les liens de ce menu. C'est le cas pour la ligne "list-style: none;", par exemple.

À vous de jouer :
Comme d'habitude, décochez tout, puis cochez une à une les lignes que nous venons de voir ci-dessus.
L'aperçu de la maquette contient un lien "Faire en sorte que le menu soit plus haut que la page". Cliquez dessus avant et après avoir coché et décoché la ligne "clear: both" de la règle #pied.
Ouvrir la maquette modifiable

Le sous-menu

Dans la section précédente, nous avons commencé à voir le code CSS du sous-menu. Nous ne réexpliquerons plus les lignes CSS composant la règle #sous-menu, mais ces lignes sont nécessaires pour transformer une banale liste <ul> en menu vertical. Le code est presque le même que pour le menu principal.

Conseil graphique sur l'ergonomie des menus :
Les liens du sous-menu font toute la longueur de ce menu : pour aller sur une page, le visiteur peut cliquer sur toute la largeur du menu, et non seulement sur le texte du lien. Je vous conseille de suivre cet exemple pour des raisons d'efficacité d'utilisation de votre site internet. En effet, la cible étant plus grande, elle est plus facilement et rapidement cliquable, sans obliger votre visiteur (qui peut être une personne non accoutumée à l'ordinateur) à viser les quelques pixels que comprends le nom du lien. Ceci est largement expliqué par la loi de Fitts, très connue en ergonomie. Pour résumer : le temps mis pour atteindre une cible est proportionnel à sa distance et inversement proportionnel à sa taille.

Voyons donc le sous-menu. La structure HTML reste la même que pour le menu principal, le CSS correspondant utilise à peu près les mêmes techniques que pour le menu principal, avec cependant quelques subtilités :

      <ul id="sous-menu">
        <li><a href="#">Lien 1</a></li>
        <li><a href="#" class="actuel">Lien 2</a></li>
        ...
      </ul>

Remarquez l'absence de balises <span>, contrairement au menu principal. En effet, tous les liens du menu auront une largeur et une hauteur fixe, nous n'avons donc pas besoin de la technique des portes coulissantes. Par contre, nous devront utiliser la technique des sprites pour un effet au survol de la souris vue plus haut. Pour cela, nous utilisons ces deux images :

sous-menu.png sous-menu-lien.png

Et le code CSS est le suivant :

#sous-menu a {
  display: block; /* Afin de pouvoir assigner une hauteur au lien (voir la règle "#menu span") */
  height: 22px; /* Hauteur de l'image sous-menu-lien.png, divisé par 2 (car elle représente deux états : normal et survolé) */
  line-height: 22px; /* Centrer le texte verticalement sur la ligne */
  background: url('images/sous-menu-lien.png'); /* Fond du sous-menu, mais devenant orange lorsque l'image est décalée vers le bas */
  text-align: center; /* Centrer le texte sur la colonne du sous-menu */
  text-decoration: none; /* Pas de soulignement des liens dans le sous-menu, ils sont déjà identifiables en tant que liens par le visiteur */
  color: #ffb400; /* Le texte est orange */
  margin: 2px 0; /* Espacer verticalement chaque bouton à l'intérieur du sous-menu */
}

#sous-menu a:hover, /* Au survol de la souris */
#sous-menu a:focus, /* Lorsque le lien a le focus, sous Firefox et autres navigateurs */
#sous-menu a:active /* Lorsque le lien a le focus, sous Internet Explorer */
{
  color: black; /* Le fond devient orange, donc le texte doit être noir pour être visible */
  background-color: #ffb400; /* L'image de fond reste inchangée, mais si l'image n'a pas été chargée, s'assurer qu'il y ait un effet visible */
  background-position: 0 -22px; /* =44 (la hauteur de l'image) / 2 : remonte l'image de fond de moitié vers le haut pour révéler sa partie orange */
}

#sous-menu .actuel { /* Indique au visiteur que ce lien est en fait la page actuellement affichée */
  font-weight: bold; /* Gras... */
  text-decoration: underline; /* ... et souligné */
}

En ayant suivit les sections précédentes, mais aussi en lisant les commentaires sur chaque ligne, vous devriez comprendre assez rapidement. J'ajouterais juste que la première ligne "display: block;" permet non seulement de pouvoir assigner une hauteur au lien, mais également à faire en sorte qu'il prenne toute la largeur du menu. Voyez l'encadré Conseil graphique sur l'ergonomie des menus au début de cette section pour plus d'explications. Pour les lignes facultatives ":focus" et ":active", voyez l'encadré Effets au focus par le clavier (:focus et :active) dans la sections Effet au survol de la souris.

À vous de jouer :
Après avoir coché toutes les lignes CSS que nous venons de voir, en incluant celle vue dans la section précédente, vous pouvez décocher les lignes "background: ..." des règles "#sous-menu" et "#sous-menu a" afin de voir les effets au survol de souris lorsque ces images n'ont pas pu ou pas encore été chargées.
Ouvrir la maquette modifiable

Le pied de page

En ce qui concerne le contenu (titres, paragraphes, liens, images...), nous n'en parlerons pas ici, car cela a été largement évoqué dans la rubrique précédente : Exemples CSS. Passons donc directement au pied de page, qui est d'une extrême complexité :

      <div id="pied">
        Paragraphe de copyrights...
      </div>

On ne peut pas faire plus compliqué, n'est-ce pas ?

pied.png

Le CSS suivant reprend et complète le CSS vu dans la section Les colonnes :

#pied {
  clear: both; /* Si le menu de gauche est plus haut que le contenu de la page, s'assurer de positionner le pied juste en dessous du menu */
  border-top: 1px solid black; /* Séparer le pied du contenu de la page */
  background: #9f9f9f url('images/pied.png'); /* (bandeau à rayures noir et orange, avec une barre grise juste en dessous) */
  font-size: 12px; /* Un peut moins que les 19 pixels de line-height */
  padding-top: 9px; /* = 8 (la hauteur de la partie hachurée noir / orange) + 1 (bordure noire) */
  height: 38px; /* = 47 (hauteur de pied.png) - 9 (le padding-top que l'on vient de définir ci-dessus) */
  line-height: 19px; /* = 38 (hauteur définie ci-dessus) / 2 (on veut deux lignes de texte dans le pied de page) */
  text-align: center; /* Center le texte horizontalement sur tout le pied de page */
  color: #444444; /* Texte gris foncé, se fondant avec le fond gris clair : moins lisible, car ce paragraphe est moins important */
}

#pied a {
  color: black; /* Les liens du pied de page doivent ressortir du reste du pied de page. C'est chose faite avec des liens noirs */
}

À vous de jouer :
Le CSS du pied de page étant assez simple, je vous renvoie à la maquette modifiable en guise d'explications. Là encore, cochez les lignes CSS de #pied dans l'ordre afin d'obtenir de petites modifications qui font avancer le site petit à petit en résolvant à chaque fois des problèmes introduits par l'activation des lignes précédentes.
Ouvrir la maquette modifiable

Compatibilité avec Internet Explorer

Revenons sur cette ligne qui se trouvait dans le <head> du code HTML de la page :

    <!--[if lt IE 8]><link rel="stylesheet" type="text/css" href="ie.css"><![endif]-->

Ceci est ce qu'on appel un commentaire conditionnel. La condition est "if lt IE 8", qui veux dire "Si le navigateur est IE (Internet Explorer) et que sa version est plus petite que 8.0 (lt 8 : Less Than 8 / Moins Que 8). Si la condition est remplie, alors le code contenu à l'intérieur du commentaire est exécuté comme s'il n'y avait pas eu de commentaire. Attention : cette technique ne fonctionne pour le moment que sous Internet Explorer, et les autres navigateurs n'ont pas montré le signe de vouloir implémenter cette fonctionnalité. Ce n'est pas très grave, car les sites fonctionnent souvent de la même manière sous tous les navigateurs, à quelques détails près sous Internet Explorer. Cela nous permet de corriger le comportement de ce navigateur.

Concrètement, cette ligne importe une seconde feuille de style pour Internet Explorer, le fichier ie.css. Les autres navigateurs ne téléchargerons pas et n'utiliserons pas ce fichier. Cette feuille de style est placée après la première, afin qu'elle remplace certaines règles CSS. Le contenu du fichier ie.css est le suivant :

/** Avec la bordure de 1px sur la page, IE démarre l'image de fond juste sous la bordure
    au lieu de commencer l'image juste après la bordure.
    On remédie à ça avec une règle spécialement conçue pour IE : */

#entete {
  background-position: 0 1px;
}

#page {
  background-position: 1px 0;
}

En effet, nous remarquons que certaines images de fond de notre maquette sont décalées d'un pixel sous Internet Explorer. Ceci est dû à un bug qui positionne ces images de fond en dessous des bordures, au lieu de les faire débuter juste après les bordures. Nous corrigeons donc ce comportement en utilisant la propriété background-position pour déplacer les images erronées de un pixel.

Au moment de l'écriture de ces lignes, Internet Explorer 8 est encore en développement, mais passe l'Acid Test 2. C'est à dire que sur certains cas très particuliers, il se comporte correctement face aux standards du Web et aux autres navigateurs. Il est donc raisonnable de penser que ce bug sera résolu avec Internet Explorer 8. C'est pour cela que nous n'appliquons cette seconde feuille de style qu'aux versions inférieures à la 8. Cela peut varier avec votre design. Et au moment de la sortie d'Internet Explorer 8, il faudra tester le site afin de savoir s'il est nécessaire de modifier la règle ou non.

Version imprimable

Comment offrir une version imprimable de vos pages ? Comment le faire rapidement, simplement, sans connaître le langage JavaScript, sans faire en sorte que vos visiteurs télécharge une seconde version de la page, optimisée pour l'impression cette fois, comment leur permettre de sauvegarder une page de votre site et de leur permettre de l'imprimer sans devoir se reconnecter pour obtenir une version imprimable ? Autant de questions qui trouveront une réponse après la pause. Oui, car en lisant cette longue page jusqu'ici, vous avez surement été très passionné, et il est possible qu'il fasse déjà nuit, que la nuit soit déjà bien avancée, voir même que vous devez aller travailler ou étudier dans quelques minutes ! Pause !

Bien, la pause étant terminée, répondons à toutes ces questions par un seul mot : CSS. Oui, le CSS va nous permettre de proposer une version imprimable de toutes vos pages, en seulement quelques lignes et sans connaissance d'un langage de programmation.
Il s'agit ici d'utiliser une caractéristique particulière du CSS : le bloc "@media" qui permet de ne prendre en compte du code CSS que pour certains médias : l'écran, l'imprimante, un diaporama, un petit écran de téléphone portable, un logiciel de synthèse vocal... En l'occurrence, nous nous intéressons au média "print", l'imprimante.

Le code CSS est le suivant, il n'a qu'à être placé à la fin du fichier CSS :

@media print {
  #menu, #sous-menu { /* Les menus et sous-menus ne servent à rien sur une feuille                     */
    display: none;    /* (en effet, on ne peut malheureusement pas les cliquer, c'est assez ballot !)  */
  }

  body {
    background: none; /* Enlever l'image de fond en forme de "grille" (au cas où le visiteur ai activé l'impression des images de fond) */
  }
  
  h1 {
    background-image: none; /* On remet le texte à la place de l'image, car par défaut, les images de fond ne sont pas imprimées */
    text-indent: 0; /* Annule la technique de remplacement de texte par une image, le texte redevient visible */
  }

  #page {
    background: none; /* Enlever l'image de fond simulant le sous-menu de gauche, car on a caché ce sous-menu */
    border: none; /* Ne plus entourer le contenu avec une bordure noire. Cela est moche sur une page imprimée, */
  }               /* et il n'y a plus besoin de séparation car on a enlevé l'image de fond en forme de grille  */

  #contenu {
    margin: 0; /* Ne plus faire de place pour le menu de gauche, qui est supprimé                             */
  }            /* De plus, les 10px de marge ne sont plus nécessaire car on a enlevé les bordures de la page, */
               /* et les feuilles imprimées ont déjà une marge                                                */
  #pied {
    border: 1px solid black; /* Les bordures bas, droite et gauche étaient réalisées par la bordure de la page             */
  }                          /* Hors, on l'a enlevée la bordure de la page. Entourer tout le pied par une nouvelle bordure */
}

Lors de l'impression de la page, le CSS habituel est toujours pris en compte, et le code "@media print" est également pris en compte. Nous nous contentons d'écraser ou redéfinir certaines définitions...

Par exemple, nous supprimons les menus : à quoi peuvent-ils bien servir sur une feuille imprimée ? Et en plus avec le sous-menu, la colonne de gauche fait perdre beaucoup de place. En supprimant le menu, le site sera surement imprimé en utilisant moins de feuilles, vos visiteurs vous en seront très reconnaissants. Et la planète aussi ! Nous supprimons également les images de fond, au cas où le visiteur en ai activé l'impression, car sur ce site précis, elles ne servent pas à grand chose. Nous annulons la technique de remplacement du titre h1 par une image du logo de la société, car par défaut, les navigateurs n'impriment pas les images de fond, donc le titre apparaîtrait vide si nous ne remettions pas le texte original. Enfin, les bordures ne sont plus nécessaires, et relèvent même d'un manque de goût une fois imprimé, nous les enlevons donc.

À vous de jouer :
Ouvrez la page du résultat global de la maquette et choisissez "Fichier" -> "Aperçu avant impression" dans votre navigateur. Vous y verrez quelque-chose comme ceci :

...

Ou alors comme cela, si vous avez activé l'impression des images de fond :

...

Un menu commun

La maquette de site de maquettes est maintenant terminée. Vous êtes désormais apte à créer un site assez complet grâce au HTML et au CSS.

Il reste cependant un point noir : l'entête HTML, l'entête visuel, les deux menus et le pied de page doivent être répétés à chaque nouvelle page HTML. Si vous modifiez le menu, alors vous devez absolument éditer toutes les pages de votre site pour y ajouter ou supprimer un lien dans le menu... C'est assez fastidieux.

C'est là qu'entre en jeu PHP. Ne fuyez pas : nous allons juste utiliser trois fois rien de PHP. PHP va nous permettre de placer le haut et le bas des pages dans deux fichiers distincts. Chaque page de votre site incorporera alors ces deux fichiers grâce à l'instruction include(), qui est une sorte de lien. On garde alors un fonctionnement similaire aux fichiers CSS : présents et modifiables en un seul endroit, mais inclus dans toutes les pages avec peu d'efforts.

PHP est un langage de programmation permettant au serveur Web de générer des pages Web dynamiquement, an allant chercher des articles dans une base de données et en créant le HTML correspondant, par exemple. Heureusement, pour avoir un menu commun, on n'ira pas aussi loin.

Mais cela veux dire que vous devez installer un serveur Web sur votre PC, afin que lors de vos tests, le PHP soit interprété. La bonne nouvelle est que cela ne prends que quelques cliques : rendez-vous sur la page de téléchargements de EasyPHP, téléchargez EasyPHP en cliquant sur le bouton Download, puis en cliquant sur le lien "EasyPHP-2.x-setup.exe" (le "x" pouvant être n'importe quel nombre). Installez le logiciel (Suivant, J'accepte, Suivant, Suivant, Suivant, Terminer ! ). Lorsqu'EasyPHP est démarré, une icône EasyPHP doit apparaître dans la zone de notification de la barre des tâches (en bas à droite de l'écran) :

...

EasyPHP n'est disponible que pour Windows. Si vous utilisez Linux ou Mac OS X, je vous laisse le soin de découvrir comment installer les paquets Apache et PHP.

Une fois EasyPHP installé et démarré, la façon de développer et tester vos pages Web vont changer légèrement :

Voici le contenu du fichier entete.php (à placer dans C:\Program Files\EasyPHP 2.x\www\site-maquette\entete.php, par exemple), représentant la partie haute de toutes les pages Web du site. Ce sera le seul fichier à éditer pour modifier les menus :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="fr">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><?php echo $titre; ?> - Maquettes Casey Steven &amp; Son</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <!--[if lt IE 8]><link rel="stylesheet" type="text/css" href="ie.css"><![endif]-->
  </head>
  <body>

    <!-- L'entête de la page, affiché tout en haut de l'écran : -->
    <div id="entete">
      <h1>Maquettes Casey Steven &amp; Son</h1>

      <!-- Le menu principal du site, affiché horizontalement, tout en haut de l'écran, juste en dessous de l'entête : -->
      <ul id="menu">
        <li><a href="#"><span>Lien 1</span></a></li>
        <li><a href="#" class="actuel"><span>Lien 2</span></a></li>
        ...
      </ul>
    </div>

    <!-- La page en elle-même, cette division sera utile pour styler le site en CSS : -->
    <div id="page">
      <!-- Le sous-menu, affiché dans une colonne sur la gauche du site : -->
      <ul id="sous-menu">
        <li><a href="#">Lien 1</a></li>
        <li><a href="#" class="actuel">Lien 2</a></li>
        ...
      </ul>

      <!-- Le contenu utile de la page, affiché sur une grande colonne à droite du site : -->
      <div id="contenu">
        <h2><?php echo $titre; ?></h2>

Notez bien que le code HTML n'est pas terminé. Ce fichier ne contient que l'entête HTML ainsi que le haut commun de la page (entête visuel, menu principal, et menu secondaire). Les deux parties jaunes <?php echo $titre; ?> sont du code PHP permettant de placer le titre réel de la page. Lors de l'exécution de la page par le serveur Web, les deux parties seront remplacées par le titre de la page, "Catalogue des bateaux", par exemple. Reportez-vous un peu plus bas, lorsque nous verrons le code du fichier index.php...

Voici le contenu du fichier pied.php, représentant la partie basse de toutes les pages Web du site (le pied de page, et les balises de fermeture d'un fichier HTML). Il sera rarement modifié et ne contient aucun code PHP :

      </div>

      <!-- Le pied de page, affiché tout en bas de l'écran. Est à l'intérieur du div "page" pour le CSS : -->
      <div id="pied">
        Paragraphe de copyrights...
      </div>
    </div>

  </body>
</html>

Voici enfin le contenu du fichier index.php (accessible dans un navigateur via http://localhost/site-maquette/index.php, par exemple). Vous pouvez copier / coller ce fichier et en modifier le contenu si vous devez créer une nouvelle page pour le site :

<?php
  $titre = "Catalogue des bateaux";
  include("entete.php");
?>
        <h3>Les bateaux qui flottent</h3>
        <p>Lorem ipsum...</p>
<?php
  include("pied.php");
?>

Concrètement, lorsque vous accéderez à la page PHP via le navigateur, la première ligne remplira la variable $titre en mémoire avec le texte "Catalogue des bateaux". Puis, la seconde ligne inclura le fichier entete.php. À l'intérieur d'entete.php, les deux bouts de code PHP seront remplacés par la valeur de la variable $titre, soit "Catalogue des bateaux". Ensuite, le reste de la page index.php ne changera pas. Enfin, la dernière ligne include() s'occupera de rapatrier le fichier pied.php, comme si vous aviez copié / collé son contenu pour remplacer le bloc include() dans index.php, mais tout ceci est automatique.

L'autre façon de faire en PHP :
En PHP, il existe une seconde méthode pour inclure les parties communes des pages. Il s'agit de placer la partie haute et basse dans index.html avec, au milieu, un appel à la fonction include() pour insérer la page voulue par le visiteur. Le visiteur accède donc aux pages du site via des URLs comme http://www.monsite.fr/index.php?url=rubrique/page.php. Je ne donnerai pas le code de cette méthode car elle est à éviter. La méthode donnée plus haut permet d'avoir des URLs plus lisible et mémorisables comme : http://www.monsite.fr/rubrique/page.php.

En effet, la méthode que je vous ai proposée permet de faire en sorte que les adresses de vos pages Web restent lisibles et surtout mémorisables, sans redirection lourde. Et c'est surtout une bonne pratique qu'il sera bon de maintenir si, plus tard, vous apprenez le PHP (ou autre langage) et commencez à rendre dynamique votre site, en accédant notamment à une base de données. Cette méthode sera moins sujette aux failles de sécurités. Principalement car les visiteurs ne peuvent pas accéder aux pages sans inclure l'entête vérifiant que l'utilisateur est connecté, par exemple.

Résumé du code

Voici des archives ZIP des diverses versions de la maquette HTML & CSS, tous téléchargeables même hors-ligne :

La maquette finale (avec les images, et la source SVG permettant de les modifier) ;
La maquette modifiable (pour modifier les fichiers plus rapidement, et sans connexion internet, inutile si vous avez téléchargé la version hors-ligne) ;
La version PHP de la maquette (à décompresser dans C:\Program Files\EasyPHP 2.x\www\site-maquette\, par exemple, et à tester avec EasyPHP).

Je voudrais également conclure en précisant que cette maquette étant assez conséquente, je vous ai appris des versions simplifiées de certaines techniques afin de ne pas trop alourdir le CSS. Ainsi, vous pouvez approfondir la technique des colonnes factices, la technique des portes coulissantes (seconde partie de l'article, et une version centrée horizontalement). Les trois derniers liens sont en anglais.

Faites une pause, vous l'avez bien mérité :
Découvrez Snaky 360, le jeu de serpent addictif réalisé par l'auteur de ce tutoriel...

Créé entièrement en HTML, CSS et JavaScript, sans Flash
(sauf pour les musiques et effets sonores, en attendant HTML 5)
Bientôt, vous pourrez en faire de même !

Ou alors, jouez à sa version Android :
Disponible sur le Play Store

Pendant qu'on y est, je peux aussi vous présenter la carte du monde que j'ai réalisé :
en très grand format pour vos murs, au design naturel et artistique :