Vala, j'ai créé il y a une paire de jours un petit tutoriel dont je me dit qu'il pourrait être utile sur HFR:
Quelqu'un trouvait joli le menu de Manga-nemesis (menu sauvegardé ici si ils le modifient, code non retouché simplement réindenté, et tout ce qui ne fait pas partie du menu a été retiré) et demandait comment faire la même chose (les têtes qui s'illuminent tout ça). Quand je suis arrivé, les réponses (4 ou 5) étaient "Avec du javascript"... ouh là, encore un menu plein de JS tout pourri?
Confirmation à la visualisation de la page: JS et tables à l'horizon, code source du menu? 14.5ko + 126ko d'images
J'ai donc décidé de montrer (et déclaré) qu'on pouvait faire la même chose sans une goutte de JS, avec simplement (x)html et CSS, compatible avec tous les browsers modernes, et en augmentant la vitesse de réaction en bonus (testez avec le menu original, si on passe rapidement la souris de gauche à droite certains boutons n'ont pas le temps de s'allumer, de plus on a un petit bug de clignottement sous Firefox).
Comme il me semble que certains fréquenteurs de hardware.fr pourraient en avoir l'utilité, je vous poste, donc, le dit tutoriel.
Edit: Attention, avant de répondre ou de commenter ayez l'obligeance de lire tout le thread et surtout la solution alternative d'OlivierPatry. Bien que non expliquée, elle est beaucoup plus claire et plus "propre" au niveau CSS (et probablement plus légère et plus courte.. en un mot, mieux )
--------------------------------------------
Tutoriel: comment créer un menu comme celui de manga-nemesis (images rollover+superposition toussa)
Prérequis:
1- Connaissance correcte du HTML/XHTML
2- Connaissance minimale des CSS (ce que c'est, comment ça s'utilise)
3- Aucune connaissance du Javascript n'est nécessaire
4- Un éditeur de texte, Notepad suffit largement, un éditeur un peu plus puissant (avec coloration syntaxique) comme SciTE ou JEdit peut être utile
I/ Le HTML.
On va commencer par construire une structure de page logique, qui veut dire quelque chose, qui soit lisible
Le menu lui même est inscrit dans une en-tête de page (un header), nous allons donc créer une structure de base comportant cette en-tête:
<?xml version="1.0" encoding="UTF-8"?>
<!-- On indique qu'on a écrit la page en UTF-8, ceci se règle dans votre éditeur de texte -->
<!-- La première ligne devant être l'encodage quand celui-ci est présent (UTF-8 ou ISO-8859-1 habituellement), on met les commentaires en dessous -->
<!-- Puis on indique que le document est conforme à la norme xhtml 1.0 du W3C
Plus d'informations à ce sujet sur cette page: http://www.w3.org/TR/xhtml1/ -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Enfin, on commence notre document à proprement parler -->
<html>
<head>
<title>Tutoriel de joli menu</title>
</head>
<body>
<div id="header">
</div>
</body>
</html> |
Voilà, une structure de base avec la localisation "logique" de l'en-tête.
On veut maintenant ajouter un menu.
Syntaxiquement, un menu peut être considéré comme une liste de liens, nous allons donc créer une liste contenant des liens (vides, mais ça n'a aucune importance)
<div id="header">
<ul>
<li><a href="#" title="Page de news">News</a></li>
<li><a href="#" title="Nos projets">Projets</a></li>
<li><a href="#" title="Notre équipe">La team</a></li>
<li><a href="#" title="Visiter le forum">Forum</a></li>
<li><a href="#" title="Nous laisser un message">Livre d'or</a></li>
<li><a href="#" title="Autres pages intéressantes">Liens</a></li>
</ul>
</div> |
On voit ici un certain nombre d'éléments:
<ul></ul> qui permet de délimiter une "liste non ordonnée"
<li></li> qui permet de délimiter un élément de liste
l'élément title des balises "a", qui permet de donner une "aide" supplémentaire, son contenu apparaît habituellement sous la forme d'un petit popup d'aide (tooltip) dans les navigateurs graphiques.
Si vous ne voulez pas le faire vous mêmes, voici le résultat
D'aucuns diront que c'est moche... peut être, mais au moins ça fonctionne et c'est clair
II/ Papy, elle est moche ta photo
Ta gueule jeune con
Bon, nous allons maintenant nous atteler à la tâche difficile de rendre ce menu joli.
Pour cela, nous allons utiliser les CSS (Cascading Style Sheed, Feuilles de Style en Cascade).
Créons donc un fichier "style.css" dans le répertoire de notre fichier HTML, puis lions les deux en ajoutant
<link rel="stylesheet" type="text/css" href="style.css" title="Style manga-nemesis" /> |
au sein de notre fichier html, à l'intérieur de la zone délimitée par <head> et </head>, comme ça
Nous allons ensuite nous munir de nos images. C'est relativement tendu dans la mesure ou les images de départ ont été ignoblement charcutées par de vils barbares, mais j'ai quand même réussi à reconstituer à peu près le bouzin.
On obtient ceci, qui en JPEG qualité 60, nous donne 83ko (trop, beaucoup trop, mais bon le matériel de départ est ainsi, et même légèrement plus lourd avec 90ko en 23 fichiers).
Et vous pouvez trouver les boutons "survolés" ici, avec un total de 22ko (JPEG qualité 80, j'ai pas trop optimisé et la q60 était trop faible à cause de la complexité & des couleurs).
Les images survolées font toutes 92px de haut (avec respectivement 139, 60, 83, 88, 108 et 108 pixels de large).
Par rapport à l'image de font d'écran, le menu commence au point (133, 247).
Dans la mesure où il n'y a pas deux éléments de liste identiques, nous devons les identifier de manière précise (ne serait-ce que pour associer à chacun une image 'de survol' ), nous allons donc utiliser les "id"s, qui permettent d'identifier un élément unique (un ID ne doit jamais se trouver deux fois dans une page donnée).
Notre liste de liens devient alors
<div id="header">
<ul>
<li id="news"><a href="#" title="Page de news">News</a></li>
<li id="projets"><a href="#" title="Nos projets">Projets</a></li>
<li id="team"><a href="#" title="Notre équipe">La team</a></li>
<li id="forum"><a href="#" title="Visiter le forum">Forum</a></li>
<li id="livre"><a href="#" title="Nous laisser un message">Livre d'or</a></li>
<li id="liens"><a href="#" title="Autres pages intéressantes">Liens</a></li>
</ul>
</div> |
Vous allez me dire "mais pourquoi donner un ID aux éléments de listes et pas aux liens?"
Réponse: nous allons devoir les manipuler, et manipuler un élément donné permet de manipuler tous ses héritiers (c'est à dire les éléments contenus à l'intérieur), nous allons voir ça dans un instant, c'est l'un des principes d'héritage et ça permet de faire des codes HTML simples.
III/ Papy, je veux pas être méchant mais elle est toujours aussi moche ta photo...
Bien, maintenant que nous avons notre fichier HTML et nos images, il nous reste à lier le tout.
Si vous l'avez fermé, rouvrez le fichier "style.css" que vous avez créé il y a 2mn.
La première chose, c'est de nettoyer le comportement par défaut des navigateurs, et on va en profiter pour mettre notre image de départ en font de l'en-tête
/* On enleve les marges et les remplissages par defaut du document et du corps de texte */
html, body {
margin: 0;
padding: 0;
}
/* on utilise #machin pour acceder à l'element d'ID "machin" */
#header {
/* On met en place notre fond en le cadrant dans le coin en haut à gauche et sans répétition */
background: url(background.jpg) top left no-repeat;
/* Et on en profite pour donner une taille à notre entete */
width: 785px;
height: 350px;
} |
L'intérêt à ce niveau là n'est pas énorme mais bon, on peut voir ici le résultat le la manoeuvre.
Il nous faut maintenant formater notre menu.
Pour cela, nous allons commencer par positionner notre liste de manière absolue (c'est à dire qu'on positionne l'élément précisément par rapport à son parent, sans tenir compte des autres éléments existants ou du flux normal de la page).
/* On accede a l'element "ul" descendant de l'element d'id "header" */
#header ul {
/* Positionnement absolut */
position: absolute;
/* Vous vous souvenez des valeurs de tout a l'heure? */
left: 133px;
top: 247px;
/* Au passage, on va enlever tout l'affichage par défaut des listes */
margin: 0;
padding: 0;
list-style: none;
}
/* Et on nettoie le comportement des elements de liste */
#header ul li {
margin: 0;
} |
Bon, le menu semble être placé à peu près au bon endroit, il nous faut maintenant... placer nos boutons.
Tout d'abord, les afficher en tant que bloc pour pouvoir leur donner une taille
#header ul li a {
/* Affichage en tant que blocs */
display: block;
} |
Mais, comme les éléments de liste, les blocs forcent le passage à la ligne.
Pas de problème, nous allons tricher: nous allons "flotter" tous les éléments vers la gauche, ce qui fait que l'élément suivant viendra se placer gentiment à leur droite.
#header ul li a {
/* Affichage en tant que blocs */
display: block;
/* Flottons flottons */
float: left;
} |
et pour IE qui nous les brise, il faut flotter les éléments de listes...
mais Opera ne supporte pas. Qu'à cela ne tienne, nous allons encore tricher !
#header ul li {
float: left;
margin: 0;
}
/* IE ne comprend pas l'instruction ci-dessous à cause du selecteur ">" */
#header ul>il {
float: none;
}
|
Il est inutile de flotter le dernière élément, on va donc lui demander de se comporter normalement juste au cas ou:
#liens a {
float: none;
} |
On obtient alors ceci.
C'est pas terrible, mais on progresse (nb: bug pascompris d'Opera sur cette étape).
Nous allons maintenant régler les tailles des boutons du menu:
#header ul li a {
/* Affichage en tant que blocs */
display: block;
/* Flottons flottons */
float: left;
/* La hauteur est commune à tous les boutons ! */
height: 92px;
}
#liens a {
float: none;
/* On rentre non la largeur de l'image mais celle du bouton: les boutons se superposent partiellement */
width: 82px;
}
#livre a {
width: 86px;
}
#forum a {
width: 74px;
}
#team a {
width: 62px;
}
#projets a {
width: 45px;
}
#news a {
width: 139px;
} |
Et comme vous pouvez le voir ici, non seulement on a des liens positionnés mais en plus on obtient une "zone" cliquable complète sur toute la surface du bouton!
Simplement grâce aux CSS !
Nous allons maintenant gérer le survol à la souris.
Ce survol se gère grâce à la pseudo classe "hover".
On peut théoriquement l'utiliser sur n'importe quel élément (d'après la norme), mais pour des raisons que personne n'a encore été capable de comprendre Microsoft a jugé bon de le restreindre au seul élément "a" dans MSIE, souvenez-vous en sous peine d'avoir des surprises.
/* Mettons en place les images survolees */
/* on appelle "element:hover" pour lui attribuer une regle de survol */
#liens a:hover {
background-image: url(hover_6.jpg);
}
#livre a:hover {
background-image: url(hover_5.jpg);
}
#forum a:hover {
background-image: url(hover_4.jpg);
}
#team a:hover {
background-image: url(hover_3.jpg);
}
#projets a:hover {
background-image: url(hover_2.jpg);
}
#news a:hover {
background-image: url(hover_1.jpg);
} |
Si vous regardez ce que donne votre page, vous vous rendrez compte... qu'elle bugge horriblement (non, pas d'image). En effet, le fond d'un élément se place par défaut au coin supérieur gauche, hors ici on a un décalage!
Nous allons donc placer le fond par rapport au coin supérieur droit des liens:
#header ul li a {
/* Affichage en tant que blocs */
display: block;
/* Flottons flottons */
float: left;
/* La hauteur est commune à tous les boutons ! */
height: 92px;
/* Modifions la référence de placement des fonds */
background-position: top right;
} |
Les positions sont parfaites mais... les images ne s'affichent que partiellement !
En effet, un fond ne peut s'afficher que sous son élément, pas en dehors ...
Nous allons donc devoir ruser (attention, ce qui va suivre peut paraître complexe, en fait après quelques temps ça vient naturellement).
Tout d'abord, redéfinir les tailles des éléments pour qu'elles correspondent aux tailles des images
#liens a {
float: none;
width: 108px;
}
#livre a {
width: 108px;
}
#forum a {
width: 88px;
}
#team a {
width: 83px;
}
#projets a {
width: 60px;
}
#news a {
width: 139px;
} |
Les images vont donc se retrouver beaucoup plus larges que précédement, et vont tout décaler par rapport au fond.
Nous allons donc les décaler en donnant une marge négative à droite à l'image située avant elles (elles vont se placer par dessus l'image précédente) égale à la surface de superposition avec l'image les précédant
#liens a {
float: none;
width: 108px;
}
#livre a {
margin-right: -26px;
width: 108px;
}
#forum a {
margin-right: -22px;
width: 88px;
}
#team a {
margin-right: -14px;
width: 83px;
}
#projets a {
margin-right: -21px;
width: 60px;
}
#news a {
margin-right: -15px;
width: 139px;
}
|
L'ordre de superposition est inversé par rapport au menu originel, mais je doute que ce soit très gênant
Comme d'habitude (ça nous change), MSIE lourde son monde en refusant de fonctionner normalement.
Résultat, la partie "superposée" refuse de s'afficher chez lui.
Vous allez donc être introduit par ce fait dans le monde des "IE Hacks":
IE ne se conforme pas à la norme sur pas mal de points, ce qui ne serait pas gênant si il ne faisait que ne pas gérer les propriétés au lieu de les interpréter "à sa sauce" (vous pouvez voir ici un certain nombre de bugs CSS d'IE). Pour lui faire adopter un rendu correct, on est donc parfois obligé d'utiliser des "hacks", c'est à dire des techniques bizarres, peu compatibles avec la norme CSS, afin de lui refiler à lui uniquement des valeurs à la con permettant un rendu visuellement correct car prenant en compte ses "spécificités".
Le hack ici est simple: le problème vient du modèle de boite d'IE, qui considère qu'une boite (un bloc) va jusqu'à l'intérieur de sa marge.
Résultat, si une marge est négative IE ne prolonge le bloc que jusqu'à la bordure ramenée à l'intérieure de la marge !
(ce qui est censé constituer "l'extérieur" de la marge et qui a été replié à l'intérieur).
Solution: supprimer toute forme de marge au moment du :hover en ajoutant ceci en fin de CSS:
/* La racine d'une page est "html", mais les IEs ajoutent un élément racine inconnu
Un navigateur compatible ignorera donc tout simplement ce qui suit, dans la mesure ou le * correspondrait a un element "html" et qu'on ne trouve pas d'element html au sein d'un autre element html.*/
* html #header a:hover {
/* Quand on passe la souris sur le lien, on retire les marges de celui-ci.
Les autres liens se decalent, mais dans la mesure ou ils ne sont pas affiches "graphiquement" la chose reste "invisible"...*/
/* Oui, c'est crade et j'ai honte, mais bon :/ */
margin-right: 0px;
} |
Le résultat, vous pouvez le voir au niveau de la 6e étape
Notre 7e étape consiste à planquer le texte des liens, que nous traînons depuis la première.
Malheureusement, nous ne pouvons le faire sans retoucher légèrement le fichier HTML: le texte de chaque lien va être placé dans une balise <span>.
C'est pas fantastique sémantiquement parlant (on a déjà 3 couches autour de notre texte ), mais essentiel pour terminer la mise en place du FIR.
Le FIR (Fahrner Image Replacement), c'est ce que nous sommes en train d'utiliser pour remplacer du texte avec des images (au niveau des liens).
Pour plus d'information sur le remplacement par des images, voir cet article de Stopdesign.
Résultat:
<div id="header">
<ul>
<li id="news"><a href="#" title="Page de news"><span>News</span></a></li>
<li id="projets"><a href="#" title="Nos projets"><span>Projets</span></a></li>
<li id="team"><a href="#" title="Notre équipe"><span>La team</span></a></li>
<li id="forum"><a href="#" title="Visiter le forum"><span>Forum</span></a></li>
<li id="livre"><a href="#" title="Nous laisser un message"><span>Livre d'or</span></a></li>
<li id="liens"><a href="#" title="Autres pages intéressantes"><span>Liens</span></a></li>
</ul>
</div> |
Puis dans notre CSS, nous effaçons le texte:
/* On reprend tout l'heritage au niveau du header */
#header ul li a span {
/* Et on demande au span de ne pas s'afficher */
display: none;
} |
Tenez, c'est tellement magique que ça conclut une étape: whoaaa
Bon, c'est pas mal, on a un joli menu qui fonctionne dans tous les navigateurs, mais il manque quelque chose !
Le texte qui s'affiche à droite du menu sur la version originelle...
Premier problème: où trouver ce texte?
Réponse: le lien qu'on vient d'effacer fera très bien l'affaire
Deuxième problème: comment positionner le texte?
Réponse: positionnement absolu !
La "boite" d'affichage de texte commence au point (633,306) et fait 152px sur 32px.
Ne pas oublier qu'on positionne le <span> par rapport au <ul>, donc une paire de soustractions pour arriver à la valeur de la position de notre bloc:
(500, 59)
#header ul a:hover span {
/* Affichage en tant que bloc */
display: block;
/* positionnement absolut */
position: absolute;
/* Position et taille */
left: 500px;
top: 59px;
width: 152px;
height: 32px;
|
On essaie ensuite de centrer le texte horizontalement (facile) et verticalement.
Pour le centrage vertical, on va définir la taille de la ligne comme faisant la hauteur de notre bloc, et aligner le texte sur le milieu de celle ci:
/* Centrage horizontal du texte */
text-align: center;
/* Redefinition de la taille de la ligne */
line-height: 32px;
/* Positionnement du texte par rapport a la ligne */
vertical-align: middle;
} |
Ne nous restent plus qu'à mettre en place la couleur et à retirer le soulignement des liens en modifiant le code CSS existant pour eux:
#header ul li a {
/* Affichage en tant que blocs */
display: block;
/* Flottons flottons */
float: left;
/* La hauteur est commune à tous les boutons ! */
height: 92px;
/* Modifions la référence de placement des fonds */
background-position: top right;
/* et on finit en modifiant l'affichage des liens */
color: #A8B4F3;
text-decoration: none;
} |
Et voilà, c'est terminé, un super menu sans la moindre ligne de JS en 5ko commentaires compris (sans compter les 105ko d'images nécessaires ).
À comparer aux 14.5ko (et 126ko d'images) de l'original
Note 1: on pourrait sûrement optimiser ce machin, et l'améliorer encore en adaptant le design à la source et non l'inverse, mais c'est déjà pas mal, et je serais probablement pas capable de faire mieux de toute façon
Note 2: Le positionnement absolu de partout pose de gros problèmes en cas de redimentionnements (ou de résolutions "imprévues" ), il est recommandé de faire des designs "fluides" capable de s'adapter à l'espace d'affichage disponible plutôt que de forcer une résolution.
Vala vala, si vous avez des questions n'hésitez pas j'essaierais d'y répondre du mieux de mes capacités
PS: le tout premier example bugge en distant sous IE (blabla erreur XML toussa), pas en local, et c'est pas très grave vu la complexité de la page (j'ai l'impression qu'il n'aime pas les commentaires entre l'entête XML et le doctype)
Message édité par masklinn le 21-02-2005 à 09:16:15
---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody