Envoyer un mail à l’auteur
xavier at ultra-fluide.com

Ressources

Portes coulissantes en CSS partie II (Sliding Doors of CSS, Part II).

par Douglas Bowman en octobre 2003, traduit en français par Xavier Boully.
L'article original publié en anglais sur A List Apart, a été traduit en français avec l'autorisation de l'auteur Douglas Bowman et de Jeffrey Zeldman au nom de A List Apart.

Les portes coulissantes en CSS (partie I) ont introduit une nouvelle technique autorisant la création d'interfaces sophistiquées sur le plan visuelle, et ce à partir d'un simple code HTML conservant les contenus textuels. Dans cette seconde partie nous allons pousser la technique encore un peu plus loin. La compréhension du présent article nécessite d'avoir parcouru la première partie.

Nous allons maintenant enrichir nos exigences : ouvrir à la possibilité qu'aucun onglets ne soit sélectionné, associer le principe des portes coulissantes avec le rollover à l'aide d'une image unique, corriger le problème relatif à la zone cliquable sous IE/Win et proposer une alternative pour la sélection des onglets. Vous trouverez les bases sur la partie I, et nous partirons directement des acquis de ce premier article.

Aucun onglet sélectionné

Nous n'avions pas pris en compte la possibilité qu'aucun onglet ne soit sélectionné. Par exemple un formulaire d'enregistrement ou un contenu juridique peuvent ne pas correspondre à aucune des sections représentées par les onglets. Si aucun des onglets ne porte l'attribut id="current", la règle qui ajoute en bas un pixel supplémentaire de padding ne sera jamais appliquée. Dans ce cas les onglets recouvrent la bordure du bas du menu.

Ajouter une bordure de 1px en bas des onglets non sélectionnés, et retirer cette bordure sur l'onglet sélectionné résout la question :

#header li {
  float:left;
  background:url("left.gif")
    no-repeat left top;
  margin:0;
  padding:0 0 0 9px;
  border-bottom:1px solid #765;
  }
#header #current {
  background-image:url("left_on.gif");
  border-width:0;
  }

Voyons le résultat avec l'exemple 7.

Rollover à une seule image

Nous avions mis les rollovers de coté dans la partie I afin d'en préserver la simplicité. Maintenant que nous avons la technique de base sous contrôle, nous allons pouvoir y intégrer les rollovers pour perfectionner notre système de menu.

Il y a peu de temps encore, introduire un effet rollover - que ce soit en javascript ou en CSS - impliquait la création de deux ensembles d'images : un pour l'état normal, et l'autre pour le survol de la souris (hover). Afin d'éviter le temps de latence constaté au survol de la souris du au chargement indépendant des images, plusieurs méthodes existent pour pré charger les images requises dans le cache du navigateur. Petr Stanicek (aka “Pixy”) nous a montré dans "Fast Rollovers, No Preload Needed" (Rollovers rapides sans pré chargement) comment combiner les deux états (normal et hover) en une seule image, éliminant ainsi la nécessité de pré chargement.

Dans notre exemple, nous empilerons nos deux images de gauche l'une au dessus de l'autre pour rassembler les deux états sur une seule nouvelle image. Nous ferons de même pour les images de droit. Les images initiales de 150 pixels vont laisser place à des images de 300 pixels de hauteur. Voici donc left_both.gif et right_both.gif. Nous utiliserons la propriété background-position pour rendre visible la zone appropriée de l'image à deux états lorsque l'utilisateur effectue un survol de l'onglet avec sa souris :

L'état normal est visible lorsque notre image à 2 états est alignée au haut de la fenêtre. Lorsque l'image est poussée vers le haut c'est l'état hover qui apparait.

Nous installons maintenant ces nouvelles images dans leurs éléments respectifs li et a, à la même position :

#header li {
  float:left;
  background:url("left_both.gif")
    no-repeat left top;
  margin:0;
  padding:0 0 0 9px;
  border-bottom:1px solid #765;
  }
#header a {
  float:left;
  display:block;
  background:url("right_both.gif")
    no-repeat right top;
  padding:5px 15px 4px 6px;
  text-decoration:none;
  font-weight:bold;
  color:#765;
  }

L'utilisation de la propriété background-position nécessite de spécifier les deux coordonnées dans cet ordre : horizontal et vertical. Il n'est pas possible de préciser le positionnement à l'aide des sous propriétés habituelles (left, right, top, etc.). Nous préciserons pour notre image de gauche une position horizontale à 0% afin que son bord gauche soit contre le bord gauche de la fenêtre visible et 100% concernant l'image de droite pour un positionnement symétrique.

Nous connaissons exactement la structure de l'image, donc son positionnement vertical peut se faire au pixel près. Les 150 pixels du haut concernent l'état normal et les 150 autres l'état hover. Donc à gauche comme à droite nous repoussons les images de 150 pixels vers le haut pour faire apparaître l'état hover. Le sélecteur #header li:hover a est répété de façon à ne spécifier la couleur de fond qu'à un seul endroit.

#header li:hover, #header li:hover a {
  background-position:0% -150px;
  color:#333;
  }
#header li:hover a {
  background-position:100% -150px;
  }

Nous utilisons les mêmes images pour l'onglet sélectionné. Ce dernier n'a qu'un état qui correspond à l'état hover de l'onglet normal :

#header #current {
  background-position:0% -150px;
  border-width:0;
  }
#header #current a {
  background-position:100% -150px;
  padding-bottom:5px;
  color:#333;
  }

Et voilà notre effet rollover implémenté, c'est aussi simple que cela. Voyons le en action dans l'exemple 8. Nous avons réduit le nombre total d'images utilisées de cinq (2 à gauche, 2 à droite, 1pour le fond) à 3 (1 à gauche, 1 à droite, 1pour le fond), et évité de recourir à un préchargement.

Si vous avez testé notre travail sous Internet Explorer (Mac ou PC), vous avez pu remarquer que le rollover ne fonctionne pas. En effet, IE n'applique la pseudo classe :hover qu'aux liens. Le mettre à la portée d'IE impliquerait un élément supplémentaire (tel qu'un élément span) à insérer dans le lien, et le décalage d'un cran de toutes nos règles (élément li vers élément a, et élément a vers élément span).

Nous n'irons pas dans le détail des ajustements nécessaires pour obtenir le rollover sous IE. Vérifiez simplement ces adaptations avec l'exemple 8a. Comme vous pouvez le constater, décaler le rôle de chaque élément élimine également la zone non cliquable mentionnée dans la partie I puisque maintenant le lien contient l'ensemble de l'onglet.

Les Rollovers sont souvent des effets d'ordre décoratif. Certains d'entre vous pourrons considérer que le code supplémentaire nécessaire pour IE n'en vaut pas le coût. D'autres penserons qu'il s'agit là d'un petit sacrifice pour avoir un effet rollover sur un navigateur populaire et éliminer en même temps la zone non cliquable. Introduire ce code supplémentaire relève de votre propre choix.

Extension de la zone cliquable sous IE/Win

Comme dans le cas des onglets de la partie I, les liens peuvent être changés en éléments block, et un padding supplémentaire peut être introduit pour étendre la région cliquable. La zone visible est le plus souvent remplie d'une couleur d'arrière plan (ou d'une image d'arrière plan dans notre exemple) ce qui laisse penser à l'internaute qu'il est possible de cliquer n'importe où dans cette zone, pas seulement sur le contenu des liens. Dans la plupart des navigateurs, lorsqu'un lien est changé en élément block (via CSS) et qu'un padding est ajouté à ce lien, sa partie visible et sa partie cliquable s'étendent concomitamment pour couvrir le contenu et le padding. Malheureusement IE/Win n'étend que la région visible et confine la région cliquable au seul contenu :

La zone cliquable s'étend dans la plupart des navigateurs à la zone visible, mais IE/Win ne rend que le texte cliquable.

Dans la partie I (et avec l'exemple 8a au dessus), nous avons noté un petit espace mort sur la gauche de l'onglet du fait de la partie transparente de l'image. Nous avions noté les conditions nécessaires pour éviter cette zone insensible à la souris. Cependant la partie I n'avait pas couvert la limitation relative à l'étroitesse de la zone cliquable sous IE/Win. Ce navigateur (version 6.0 et inférieures) souffre de plusieurs bogues dans l'implémentation de CSS. Certains bogues produisent des problèmes inattendus - et parfois même non répertoriés - pour l'utilisation et l'accessibilité de systèmes de navigation basés sur CSS.

Spécifier la largeur ou la hauteur d'un lien va forcer IE comme par magie à étendre sa région cliquable. Mais cela s'opposerait à la flexibilité que nous attendons de la taille des onglets. Vous pensez peut-être que nous pourrions spécifier une hauteur ou une largeur en "em". Cela réglerait la taille des onglets sur la taille de la police du texte contenu par héritage. Mais utiliser une hauteur sur un lien rend IE/Win complètement fou. Concernant la largeur, à moins d'utiliser une police à espacement fixe, la déterminer en em va rendre la largeur de l'onglet inappropriée par rapport au texte dont la largeur aura été réévaluée. (Sans compter la lourdeur due à la nécessité de déterminer une largeur pour chaque onglet en fonction du texte qu'il contient).

Heureusement pour nous, nous allons pouvoir exploiter un autre défaut de IE/Win dans son implémentation de CSS, le forçant à étendre la zone cliquable sans pour autant déterminer une largeur arbitraire. Tout ce que nous devons faire est de spécifier une très petite largeur sur le lien. La plupart des navigateurs sont stricts dans l'application de la largeur d'un élément block, indépendamment de la largeur du contenu : l'élément va se réduire à la largeur spécifiée même si son contenu doit dépasser ses frontières. Au contraire IE/Win réduit l'élément à la largeur de la plus longue ligne de texte insécable.

Donc même si nous spécifions une largeur vraiment étroite (.1em par exemple), IE/Win va tout de même rendre le lien aussi large que son contenu. Dans le même temps IE va étendre la région cliquable jusqu'à remplir tout l'onglet :

#header a {
  float:left;
  display:block;
  width:.1em;
  background:url("right.gif")
    no-repeat right top;
  padding:5px 15px 4px 6px;
  text-decoration:none;
  font-weight:bold;
  color:#765;
  }

Ceci parait n'avoir aucune logique, dans la mesure ou les deux idées vont en sens opposées. Cependant le problème de la zone cliquable réduite sous IE./Win est maintenant résolue. Maintenant nous devons garder à l'esprit que les autres navigateurs vont coller à la spécification et réduire la largeur de l'onglet à .1em + padding. Heureusement, IE/Win (6.0 et inférieure) ne comprend pas le sélecteur d'enfant , caractéristique qui nous facilite la tâche pour remettre la largeur à la valeur auto en direction des autres navigateurs, et laisser ainsi la taille des onglets libre :

#header > ul a {width:auto;}

L'exemple 9 présente cette solution.

Le ciblage des onglets

Jusqu'à présent, un seul des onglets était ciblé à l'aide de l'attribut id pour en faire l'onglet sélectionné. Changer la position de l'attribut id d'un onglet à l'autre est simple à comprendre pour qui débute sur CSS. Cependant, il existe un autre moyen de cibler l'onglet sélectionné, peut-être plus efficace dans bien des cas, même si en contrepartie cette méthode nécessite l'ajout d'un peu de code.

Au lieu d'utiliser id="current" pour identifier l'onglet sélectionné, nous pourrions appliquer un identifiant unique pour chaque onglet :

<div id="header">
  <ul>
    <li id="nav-home"><a href="#">Home</a></li>
    <li id="nav-news"><a href="#">News</a></li>
    <li id="nav-products"><a href="#">Produits</a></li>
    <li id="nav-about"><a href="#">A propos</a></li>
  </ul>
</div>

Nous appliquons également un identifiant à un container plus large, l'élément body par exemple. Cet identifiant correspond à une rubrique dans laquelle cette page s'insère. L'identifiant positionné sur l'élément body peut également servir pour appliquer un style spécifique à la rubrique dans d'autres parties de la page. Cces identifiants localisés aux deux endroits, permettent de modifier l'apparence de certains onglets lorsque les conditions des sélecteurs descendants sont remplies. Plutôt que d'introduire #current dans le sélecteur, nous utiliserons la combinaison des identifiants de l'élément body et des items de la liste pour définir l'onglet sélectionné :

#home #nav-home, #news #nav-news,
#products #nav-products, 
#about #nav-about  {
  background-position:0% -150px;
  border-width:0;
  }
#home #nav-home a, 
#news #nav-news a,
#products #nav-products a, 
#about #nav-about a  {
  background-position:100% -150px;
  color:#333;
  padding-bottom:5px;
  }

L'exemple 10 montre le résultant lorsque l'on applique id="news" à l'élément body, et l'exemple 10a applique id="products".

Notes complémentaires

Structure d'entête : Il se peut que vous ayez sur vos pages des blocks qui structurent le haut de page et rehaussent d'un rectangle par exemple l'entête et son contenu. En supposant que vous utilisez un container (une div par exemple) pour emballer cette construction, vous disposez donc de deux éléments (la div et l'entête) pour l'image de fond. Dans ce cas, vous préférerez placer l'image étroite de l'onglet à droite comme dans l'exemple 2. Cela donne effectivement un contrôle complet sur la position du texte à gauche. On peut également s'arranger pour fondre le bas de chaque image dans la couleur du fond de l'enveloppe pour donner l'impression que tout est d'un seul tenant.

Rotation de 90° : Si vous pouvez prévoir approximativement la hauteur d'un élément d'interface (ou si vous avez des images qui laissent suffisamment de marge pour absorber des variations en hauteur), vous pouvez tournez la "porte" de 90°, et utiliser une image pour le haut et une image pour le bas (au lieu d'une répartition droite gauche). Il faut cependant prévoir une largeur suffisante qui puisse accepter les variations de taille du texte que l'utilisateur peut imposer dans son navigateur.

Scintillement sous IE : Si vous voyez les images scintiller (voire clignoter) au survol de la souris dans IE/Win, vérifiez les préférences concernant la gestion du cache (Outils > Options Internet > Onglet général > Paramètres). Vous avez peut-être changé les valeurs par défaut afin de recevoir systématiquement la dernière version de la page visitée. IE/Win a un problème pour maintenir la stabilité des images en arrière plan des liens avec le paramétrage "A chaque visite de la page". Le paramètre par défaut est "Automatiquement", il permet au navigateur de chercher l'image dans le cache, évitant ainsi tout scintillement. La plupart des utilisateurs ne change jamais cette préférence, et souvent ils ignorent même son existence.
Note du traducteur : il existe d'autres solutions pour éviter le scintillement sous IE

Onglets de plusieurs mots : Si vous avez besoin, comme on le voit souvent, de définir le texte des onglets avec plusieurs mots, vous devriez ajouter white-space:nowrap; à la règle définissant le comportement des liens. Cela évitera un retour à la ligne entre deux mots dans un onglet.

Il y a certainement d'autres choses à dire sur cette technique pour corriger des défauts, l'améliorer ou la perfectionner. Nous nous arrêterons ici cependant, espérant avoir déjà répondu à nombre de questions relativement à cette technique souple et bien pratique des portes coulissantes.


Agence de communication Ultra-Fluide : 01 47 70 23 32 - contact at ultra-fluide.com - 44 rue Richer 75009 Paris.