Les Portes Coulissantes de CSS
Par Douglas Bowman
Un des avantages de CSS rarement évoqué est la capacité de superposer des images d'arrière-plan, permettant de glisser l'une par-dessus l'autre pour créer certains effets. CSS2 en l'état requiert un élément HTML distinct pour chaque image de fond. Dans de nombreux cas, le balisage type pour des composants d'interface courants nous fournit déjà plusieurs éléments à utiliser.
L'un de ces cas est la navigation par onglets. Les onglets jouissent d'une popularité grandissante en tant que moyen de navigation primaire, et il est temps d'en reprendre le contrôle. Maintenant que CSS est largement supporté, nous pouvons améliorer la qualité et l'apparence des onglets sur nos sites. Vous savez probablement que CSS peut être utilisé pour apprivoiser une simple liste non ordonnée. Vous avez peut-être même déjà vu des listes habillées comme des onglets, ressemblant à quelque chose comme çeci :
Et si on pouvait prendre le balisage exact tel qu'utilisé pour les onglets ci-dessus, et les transformer en quelque chose comme çeci :
Avec quelques styles, nous le pouvons.
Où est l'innovation ?
Nombreux sont les onglets à base de CSS que j'ai vu souffrir des mêmes attributs génériques : des fonds de couleur tout carrés, parfois un contour, une bordure qui disparaît pour l'onglet actif, un changement de couleur en guise de rollover. C'est tout ce que CSS peut nous offrir ? Quelques boîtes et des couleurs unies ?
Avant que CSS ne soit plus largement adopté, on commençait à voir de nombreuses innovations dans la conception de navigations : des formes inventives, des fondus de couleurs maîtrisés, et l'imitation d'interfaces physiques du monde réel. Mais ces concepts reposaient lourdement sur des constructions complexes d'images textuelles, ou des imbrications multiples de tableaux. Tout redimensionnement du texte était impossible, ou provoquait des problèmes significatifs dans la mise en page.
Une navigation purement textuelle est bien plus facile à entretenir et se charge plus rapidement qu'une navigation en images. De même, bien qu'on puisse ajouter des attributs alt
à chaque image, le texte pur est encore plus accessible puisqu'il peut être redimensionné par les utilisateurs à la vision déficiente. Il n'est pas étonnant que la navigation à base de texte seul, stylée avec des CSS, resurgisse dans le web design. Mais la plupart des principes d'onglets basés sur CSS sont visuellement des retours en arrière par rapport à ce que nous avions l'habitude de faire (rien en tout cas qu'on inclurait dans un portfolio). Une technologie à l'adoption récente (comme CSS) devrait permettre de créer quelque chose de mieux, sans perdre la qualité de design de nos précédents onglets bidouillés en tableaux et en images.
La techniques des Portes Coulissantes
En utilisant deux images d'arrière-plan distinctes, nous pouvons créer des composants d'interface élégamment taillés, réellement flexibles, qui se contractent et se dilatent en même temps que la taille du texte. Il suffit d'une image à gauche, et d'une à droite. Pensez-y comme à des portes coulissantes qui ferment une entrée. Les portes se rejoignent et se recouvrent de plus en plus pour remplir un espace étroit, ou s'écartent en se recouvrant de moins en moins pour remplir un espace plus large, comme sur le schéma ci-dessous :
Avec ce modèle, une image recouvre une partie de l'autre. Si on assume que nous avons un élément unique sur les bords extérieurs de chaque image, comme le coin arrondi d'un onglet, nous voudrons éviter que l'image de devant n'obscurcisse complètement celle de derrière. Pour s'en assurer, rendons l'image de premier plan (celle de gauche pour cet exemple) la moins large possible. Mais gardons-la juste assez grande pour révéler l'élément unique de son côté. Si les coins externes sont arrondis, nous devrions rendre l'image de premier plan juste assez large pour contenir la portion courbe du dessin :
Si l'objet devait dépasser la largeur illustrée ci-dessus, à cause d'un texte long ou d'un changement de corps de police, les images s'éloigneront l'une de l'autre, créant un vilain trou. Nous devons donc faire un choix arbitraire sur la fourchette de redimensionnement envisagée. Jusqu'à quelle largeur l'objet risque t-il de grandir en fonction du redimensionnement du texte dans un navigateur ? Nous devrions probablement compenser un agrandissement d'au moins 300%. Pour cela il faut étendre l'image d'arrière-plan. Pour l'exemple d'aujourd'hui nous allons faire une image de fond (celle de droite) de 400x150 pixels, et une image de premier plan de 9x150 pixels.
Gardez à l'esprit que les images d'arrière-plan apparaissent seulement dans le «passage » disponible de l'élément auquel elles sont appliquées (la zone de contenu + le padding
). Les deux images sont ancrées aux coins extérieurs de leurs éléments respectifs. Les parties visibles de ces images de fond s'assemblent à l'intérieur du passage pour ressembler à un onglet :
Si l'onglet est forcé vers une taille plus grande, les images coulissent vers l'extérieur, remplissant un passage plus large, et révélant un peu plus de chaque image :
Dans cet exemple, j'ai utilisé Photoshop pour créer deux images d'onglets doux, légèrement en relief, ceux qui sont présentés au début de cet article. Pour l'un des onglets, le dégradé a été éclairci et les bords assombris - la version claire sera utilisée pour représenter l'onglet actif. À cause du modèle de cette technique pour les images gauche et droite de l'onglet, nous devons étendre la zone couverte par l'image et la couper en deux morceaux :
Il faut opérer de même avec l'image plus claire de l'onglet actif. Quand les quatre images sont créées (1, 2, 3, 4), nous pouvons passer au balisage et aux CSS pour nos onglets.
Création des onglets
À mesure que vous explorez la création de listes horizontales avec CSS, vous noterez au moins deux méthodes pour arranger un groupe d'éléments en ligne. Chacune comporte ses avantages et ses inconvénients. Chacune demande de devoir gérer certains aspects un peu louches de CSS qui peuvent rapidement devenir déroutants. L'une utilise les boîtes en-ligne (inline
), l'autre requiert float
.
La première méthode - probablement la plus courante - change l'affichage de chaque item de liste en display: inline
. La méthode en-ligne est attirante de par sa simplicité. Toutefois, appliquée à la technique des Portes Coulissantes, elle cause quelques problèmes d'affichage dans certains navigateurs. La deuxième méthode, sur laquelle nous allons nous concentrer, utilise float
pour placer chaque item de liste sur une ligne horizontale. float
peuvt s'avérer aussi tout aussi frustrant que la méthode en-ligne. Son comportement apparemment incohérent échappe à toute logique. Pourtant, une compréhension basique de la manière de gérer de multiples éléments flottants permet de faire des merveilles.
Nous allons imbriquer plusieurs éléments flottants dans un élément conteneur, lui aussi flottant. Il faut faire cela pour que le parent flottant englobe complètement les éléments flottants intérieurs. De cette manière, nous pouvons ajouter une couleur de fond et/ou une image derrière nos onglets. Il est important de se souvenir que l'élément suivant directement nos onglets doit réinitialiser sa propre position en utilisant la propriété CSS clear
. Cela empêche les onglets flottants d'affecter la position d'autres éléments dans la page.
Commençons avec le balisage suivant :
<div id="header">
<ul>
<li><a href="/traduction/portescoulissantes#">Home</a></li>
<li id="current"><a href="/traduction/portescoulissantes#">News</a></li>
<li><a href="/traduction/portescoulissantes#">Products</a></li>
<li><a href="/traduction/portescoulissantes#">About</a></li>
<li><a href="/traduction/portescoulissantes#">Contact</a></li>
</ul>
</div>
En réalité, le div #header
pourrait aussi contenir un logo et un champ de recherche. Pour notre exemple, nous allons raccourcir la valeur de href
dans chaque ancre. Evidemment, ces valeurs devraient normalement contenir des adresses de fichiers ou de répertoires.
Commençons à habiller nos listes en flottant le conteneur #header
. Cela permet de s'assurer que le conteneur «contient » effectivement les items de liste qui seront aussi flottants. Puisque l'élément est flottant, nous devons aussi lui assigner une largeur de 100%. Une couleur de fond jaune est temporairement ajoutée pour vérifier que le parent s'étire sur la totalité de la zone derrière les onglets. Définissons aussi quelques propriétés de texte par défaut, nous assurant que tout ce qui est à l'intérieur sera identique :
#header {
float:left;
width:100%;
background:yellow;
font-size:93%;
line-height:normal;
}
Pour l'instant, établissons aussi les valeurs par défaut de margin
et padding
pour la liste et ses éléments à "0", et enlevons les puces. Chaque item de liste est aussi flottant à gauche :
#header ul {
margin:0;
padding:0;
list-style:none;
}
#header li {
float:left;
margin:0;
padding:0;
}
Transformons les ancres en éléments de type bloc pour en garder le contrôle sans nous soucier du modèle en-ligne :
#header a {
display:block;
}
Ensuite, ajoutons notre image de fond du côté droit aux items de liste (les changements/ajouts sont en gras) :
#header li {
float:left;
background:url("norm_right.gif")
no-repeat right top;
margin:0;
padding:0;
}
Avant d'ajouter l'image du côté gauche, faisons une pause pour voir où nous en sommes, dans l'exemple 1. (Dans le fichier exemple, ignorez les règles que j'ai appliqué à body
. Elles donnent seulement des valeurs de base pour les marges, le padding
, les couleurs et le texte.)
- - -
Nous pouvons maintenant placer l'image de gauche devant celle de droite en l'appliquant à l'ancre (notre élément interne). Ajoutons le padding
en même temps, pour étendre l'onglet et décoller le texte des bords :
#header a {
display:block;
background:url("norm_left.gif")
no-repeat left top;
padding:5px 15px;
}
Cela nous donne l'exemple 2. Notez comme les onglets ont commencé à prendre forme. À cette étape, un mot pour les utilisateurs perdus d'IE5/Mac, qui se demandent Mais qu'est-ce qui se passe ici ? Les onglets sont empilés verticalement et s'étirent sur tout l'écran !
Ne vous inquiétez pas, on s'occupe bientôt de vous. Pour l'instant faites de votre mieux pour suivre, ou passez temporairement sur un autre navigateur si vous le pouvez, et soyez sûrs que nous traiterons rapidement le problème.
- - -
Maintenant que les images de fond sont en place pour les onglets normaux, nous devons changer les images utilisées pour l'onglet actif. Faisons-le en ciblant l'item de liste dont id
="actif" et l'ancre qu'il contient. Puisque nous n'avons pas besoin d'altérer d'autres aspects de l'arrière plan que l'image, utilisons la propriété background-image
:
#header #current {
background-image:url("norm_right_on.gif");
}
#header #current a {
background-image:url("norm_left_on.gif");
}
Nous avons besoin d'une sorte de bordure en-dessous de nos onglets. Mais appliquer une propriété border
au conteneur #header
ne nous permettra pas de «fondre » l'onglet actif dans cette bordure. Au lieu de cela, créons une nouvelle image avec la bordure que nous voulons inclure sous cette image. Pendant que nous y sommes, ajoutons un subtil dégradé pour qu'elle ressemble à ceci :
Appliquons cette image à l'arrière plan de notre conteneur #header
(au lieu de la couleur jaune que nous avions), poussons l'image de fond en bas de l'élément, et utilisons une couleur de fond assortie au haut de cette nouvelle image. Dans le même temps, supprimons le padding
de l'élément body
que j'avais inséré à l'origine, et appliquons 10 pixels de padding
au côtés haut, gauche, et droit de ul
:
#header {
float:left;
width:100%;
background:#DAE0D2 url("bg.gif")
repeat-x bottom;
font-size:93%;
line-height:normal;
}
#header ul {
margin:0;
padding:10px 10px 0;
list-style:none;
}
Pour compléter l'effet d'onglet, nous devons fondre l'onglet actif dans la bordure, comme mentionné ci-dessus. On pourrait appliquer border-bottom
à nos onglets, dans une couleur assortie à celle de la bordure de l'image de fond de #header
, puis qu'on passerait en blanc pour l'onglet actif. Cependant, cette méthode provoquerait un minuscule décalage, dérangeant pour une précision au pixel près. Au lieu de cela, si nous modifions le padding
des ancres, nous pouvons créer des coins parfaitement équarris à l'intérieur de l'onglet actif, comme illustré dans l'exemple agrandi ci-dessous :
Accomplissons ceci en diminuant d'un pixel le padding-bottom
de l'ancre normale (5px - 1px = 4px), puis en rajoutant ce pixel à l'ancre active :
#header a {
display:block;
background:url("norm_left.gif")
no-repeat left top;
padding:5px 15px 4px;
}
#header #current a {
background-image:url("norm_left_on.gif");
padding-bottom:5px;
}
Le changement permet à la bordure inférieure d'apparaître pour les onglets normaux, tout en la cachant pour l'onglet actif. Ceci amène notre code à l'exemple 3.
Touches finales
Vos yeux de lynx auront noté des coins blancs apparaissant dans l'exemple précédent. Ces coins opaques empêchent pour l'instant l'image de fond de transparaître à travers le coin gauche de l'image de premier plan. En théorie, nous pourrions essayer d'accorder les coins des images d'onglets à une partie du fond derrière elles. Mais nos onglets peuvent s'agrandir en hauteur, ce qui pousse l'arrière plan vers le bas en décalant la couleur que nous voulions assortir. Changeons plutôt les images, en rendant transparents les coins de nos onglets. Si les courbes sont lissées, la transparence sera choisie d'après une moyenne de la couleur de fond derrière elles.
Maintenant que les coins sont transparents, un morceau de l'image de droite apparaît à travers le coin de l'image de gauche. Pour compenser ceci, ajoutons à l'item de liste une petite quantité de padding
gauche équivalent à la largeur de l'image de gauche (9px). Du padding
ayant été ajouté à l'item de liste, nous devons en enlever autant à l'ancre pour conserver le centrage du texte (15px - 9px = 6px) :
#header li {
float:left;
background:url("right.gif")
no-repeat right top;
margin:0;
padding:0 0 0 9px;
}
#header a {
display:block;
background:url("left.gif")
no-repeat left top;
padding:5px 15px 4px 6px;
}
Toutefois nous ne pouvons pas en rester là, parce que notre image de gauche est maintenant repoussée du bord gauche de l'onglet par les 9 pixels que nous venons d'ajouter. Maintenant que les bords intérieurs des passages visibles droit et gauche s'accolent, nous n'avons plus besoin de garder l'image de gauche au premier plan. Nous pouvons donc intervertir l'ordre des deux images de fond, en l'appliquant aux éléments opposés. Nous devons aussi intervertir les images utilisées pour l'onglet actif :
#header li {
float:left;
background:url("left.gif")
no-repeat left top;
margin:0;
padding:0 0 0 9px;
}
#header a, #header strong, #header span {
display:block;
background:url("right.gif")
no-repeat right top;
padding:5px 15px 4px 6px;
}
#header #current {
background-image:url("left_on.gif");
}
#header #current a {
background-image:url("right_on.gif");
padding-bottom:5px;
}
Cela fait, nous arrivons à l'exemple 4. Notez que les manipulations nécessaires pour rendre les coins transparents créent un petit espace mort sur le côté gauche de l'onglet quand il n'est pas cliquable. L'espace mort est en dehors de la zone de texte, mais il est légèrement visible. Utiliser des images transparentes pour chaque côté de nos onglets ne sera pas nécessaire. Si nous ne préférons pas avoir ce petit espace mort, nous devons utiliser une couleur pleine derrière les onglets, puis utiliser cette couleur pour le coin de nos images d'onglets au lieu de les rendre transparents. Pour l'instant, nous allons conserver nos coins transparents.
- - -
Pour les modifications restantes, nous allons faire plusieurs changements d'un seul coup : passer en gras tous les textes d'onglets, donner une couleur marron au texte normal, colorer le texte d'onglet actif en gris foncé, enlever les soulignements de liens, et passer la couleur de texte des liens survolés dans le même gris foncé. Tous les ajouts et modifications sont maintenant présents dans l'exemple 5.
Une bidouille pour la cohérence
Après l'exemple 2, nous avons identifié un problème avec IE5/Mac où chaque onglet s'étire sur toute la largeur du navigateur, forçant chacun à s'empiler verticalement sur le suivant. Pas tout à fait l'effet que nous recherchions.
Dans la plupart des navigateurs, flotter un élément le réduit à la plus petite taille possible de son contenu. Si un élément flottant contient (ou est) une image, sa taille diminuera jusqu'à celle de l'image. S'il ne contient que du texte, il rétrécira jusqu'à la largeur du mot le plus long.
Le problème survient pour IE5/Mac quand un élément de type bloc à largeur automatique est inséré dans un élément flottant. Les autres navigateurs vont rétrécir l'élément flottant à sa plus petite taille possible, indépendamment de l'élément de-type bloc qu'il contient. Mais IE5/Mac n'applique pas ce rétrécissement. Au contraire, il étend le flottement et l'élément de type bloc à toute la largeur disponible. Pour contourner ce problème, nous devons flotter l'ancre, mais seulement pour IE5/Mac, de peur de perdre les autres navigateurs. Modifions d'abord la règle existante pour flotter l'ancre. Puis nous nous servirons du Commented Backslash Hack pour cacher une nouvelle règle à IE5/Mac annulant le flottement dans tous les autres navigateurs :
#header a {
float:left;
display:block;
background:url("right.gif")
no-repeat right top;
padding:5px 15px 4px 6px;
text-decoration:none;
font-weight:bold;
color:#765;
}
/* Commented Backslash Hack
Cache des règles à IE5-Mac \*/
#header a {float:none;}
/* Fin du hack IE5-Mac */
Les navigateurs IE5/Mac devraient maintenant afficher les onglets comme prévu, selon l'exemple 6. Rien ne devrait avoir changé pour les autres navigateurs. Notez que IE5.0/Mac souffre d'un nombre important de bugs de rendus qui ont été corrigés dans la mise à jour vers IE5.1. Pour cette raison, la technique des Portes Coulissantes peine dans la version 5.0 à un point que je renonce à essayer de bidouiller. La mise à jour vers IE5.1/Mac étant disponible depuis un certain temps maintenant, le pourcentage de Macs OS9 comportant encore IE5.0 devrait s'être réduit à peau de chagrin.
Variations
Nous venons de parcourir la technique des Portes Coulissantes pour créer une navigation par onglets avec du texte pur, balisée avec une liste de liens non ordonnée, altérée grâce à quelques styles maison. Elle se charge vite, s'entretient facilement, et le texte peut être redimensionné vers le haut ou le bas de manière significative avant de casser la mise en page. Faut-il encore mentionner à quelle point cette technique est suffisamment flexible pour créer n'importe quel type de navigation d'allure sophistiquée ?
Les applications de cette technique ne sont limitées que par votre imagination. Notre exemple final représente une possibilité, mais ne laissez pas un seul exemple brider vos idées.
Par exemple, les onglets n'ont pas besoin d'être symétriques. J'ai rapidement créé une Version 2 de ces onglets, qui évitent le style 3D ombré en faveur de couleurs pleines, de coins angulaires, et d'un côté gauche plus large et détaillé. On peut changer l'ordre des images droite/gauche, selon le design, comme le montre la Version 2. Avec une bonne préparation et quelques manipulations d'image élaborées, on pourrait abandonner la bordure inférieure pour assortir les images des onglets au fond général derrière eux, comme le montre ma version 3 à l'inspiration Arts-Déco. Si votre navigateur permet le changement de styles à la volée, vous pouvez même visualiser ce fichier maître et basculer entre les trois versions différents en alternant les feuilles de styles.
D'autre effets que nous ne couvrons pas ici pourraient être rajoutés. Dans l'exemple de cet article, j'ai changé la couleur de texte pour l'état survolé, mais des images entières pourraient être interverties pour créer des rollovers intéressants. À chaque fois que deux éléments HTML imbriqués préexistent dans le balisage, CSS peut être utilisé pour des effets de couches d'images que nous n'avons même pas encore commencé à imaginer. Nous avons créé dans cet exemple une ligne horizontale d'onglets, mais les Portes Coulissantes pourraient être utilisées dans beaucoup d'autres situations. Qu'allez vous en faire ?
> Les Portes Coulissantes de CSS, Chapitre II
http://www.alistapart.com/articles/slidingdoors/