w3qc.org

w3qc.org

Comment mettre un lien «Haut de page» en position fixe? | W3Québec

par Normand Lamoureux, octobre 2005

Pour aider à la navigation, certains sites mettent à la disposition des utilisateurs un lien vers le haut de page. Il arrive que ce lien soit intégré de telle manière qu’il reste toujours situé au même endroit dans la fenêtre. Voici comment mettre en place un tel dispositif.

Le code HTML

On se sert d’un lien-image ordinaire, dont voici le code HTML :


 
  Haut de page.
 

Essentiellement, on a une image () insérée dans un lien (), lui-même inséré dans un conteneur générique ().

Le lien

Le lien sert à ce que l’image soit cliquable. Faire pointer ce lien vers l’URI de la page permettrait de retourner où on veut, mais en forçant d’abord le navigateur à recharger le document. Ce qu’on peut éviter en mettant simplement href="#". Un clic sur ce lien et le navigateur se positionnera en haut de page, sans avoir besoin de recharger le contenu.

Le conteneur

Comme un lien ne peut pas être enfant immédiat de , on le met dans un conteneur générique . Un conteneur

aurait aussi pu fonctionner, mais comme l’image contenue dans ce lien n’est pas vraiment un paragraphe, est plus sensé.

Afin de pouvoir maîtriser le positionnement de cette image à l’exclusion de toute autre qui se trouverait dans la page, on a identifié le conteneur avec id="hdp", où « hdp » vaut pour « Haut de page ». Ce choix de nom est arbitraire, mais il est plus parlant que si on avait mis id="xyz" ou n’importe quoi d’autre.

L’image elle-même

Reste le code de l’image. Les dimensions de l’image ont été explicitement définies avec width et height pour que le navigateur n’ait pas à les calculer. Plus la page contient un grand nombre d’images, plus il sera indiqué d’en définir les dimensions explicitement pour ne pas ralentir le processus d’affichage.

On a écrit alt="Haut de page." pour que les personnes qui ne voient pas l’image disposent tout de même un moyen de savoir à quoi elle sert. Le point final forcera la synthèse vocale des logiciels d’adaptation à marquer une pause. Ce que les utilisateurs apprécieront.

Enfin, on a indiqué "Haut de page" comme valeur à l’attribut title pour qu’une infobulle (ou bulle d’aide pour les adeptes de la pomme!) s’affiche au survol de la souris. Internet Explorer afficherait le contenu de l’attribut alt sans avoir besoin de ce title, mais il s’agit d’un comportement fautif qu’il est seul à adopter. Pour afficher un complément d’information sous forme d’infobulle, il faut donc utiliser l’attribut title.

Le code CSS

Lorsqu’une propriété CSS n’est pas bien supportée, la meilleure façon de procéder consiste à développer d’abord le code pour les navigateurs qui la comprennent, puis à faire les ajustements qui s’imposent pour que les résultats soient acceptables dans les navigateurs qui ne la comprennent pas. D’où les sections qui suivent.

S’adresser d’abord aux navigateurs conformes

Trouver le bon sélecteur

Pour contrôler une image par CSS, il faut d’abord trouver un moyen de s’adresser à elle à l’exclusion de tout autre élément de la page. Ce que le sélecteur div#hdp img permet de faire.

Mettre la bordure de l’image à zéro

Par défaut, une image dans un lien sera affectée d’un bordure de 2 pixels. Comme on ne veut pas d’une telle bordure, on la retire tout simplement avec border:0;.

Maîtriser le comportement de l’image

Il existe plusieurs types de positionnement CSS. Celui qui nous intéresse, position:fixed;, signifie au navigateur qu’on a l’intention de figer un élément de manière à ce qu’il reste immobile pendant que le reste du contenu se meut lorsqu’on fait défiler la page.

Définir la position de l’image

Outre le type de positionnement à utiliser, on peut encore demander au navigateur de placer l’image à un endroit précis. Dans le cas de l’image utilisée sur le site du W3Québec (flèche blanche dans un carré bleu), l’image est placée à 300 pixels du haut et à 25 pixels du bord droit de la zone d’affichage de la fenêtre. Ce qu’on fait avec top:300px; et right:25px;.

En résumant ce qui précède, on obtient le code CSS suivant :

div#hdp img {
     border:0;
     position:fixed;
     top:300px;
     right:25px;
}

S’adresser à Internet Explorer ensuite

Retoucher au code source

Normalement, le code mis au point devrait suffire, mais Internet Explorer ne comprend pas position:fixed;. Comme toujours, lorsqu’une règle CSS n’est pas supportée, elle est tout simplement omise. C’est pourquoi l’image n’aura ni le comportement ni la position souhaitée dans Internet Explorer.

Comme cette limite d’IE ne peut pas être contournée au moyen d’un hack CSS, il faut trouver un compromis acceptable, qui consiste à faire que l’image se trouve à la fin du document, et positionnée près du bord droit de la fenêtre.

Pour que l’image apparaisse à la toute fin, le plus simple est de s’arranger pour que le code HTML qui lui correspond apparaisse assez loin dans le code source. On conviendra de le mettre à la toute fin.

Construire la règle voulue pour Internet Explorer

L’image étant placée à la fin du contenu – donc au meilleur endroit stratégique pour l’utilisation qui en sera faite –, on la positionne à l’endroit souhaité, soit à 25 pixels du bord droit de la fenêtre.

La déclaration float:right; poussera l’image à l’extrême droite du navigateur. Il faut ensuite la décaler de 25 pixels vers la gauche. Ce que margin-right:25px; permettrait de faire, mais comme il faut aussi remonter l’image à la verticale de 40 pixels, mieux vaut y aller tout de suite avec position:relative;, right:25px; et top:-40px;.

Dans Internet Explorer, la règle CSS qui suit sera enfin comprise :

div#hdp img {
     border:0; 
     float:right;
     position:relative; 
     right:25px; 
     top:-4em; 
}

Choisir la meilleure stratégie

Ce travail fait, on se retrouve avec deux règles CSS distinctes.

Une, comprise par les navigateurs conformes, mais pas par Internet Explorer :

div#hdp img {
     border:0; 
     position:fixed; 
     top:300px; 
     right:25px;
}

et une autre, comprise par tous :

div#hdp img {
     border:0; 
     float:right;
     position:relative; 
     right:25px; 
     top:-4em; 
}

Laisser ces deux règles telles quelles et dans cet ordre fera que la seconde aura préséance sur la première. Pour la simple et bonne raison que ce qu’on dit d’abord (position:fixed;) est contredit ensuite (position:relative;). Ce qu’on veut, plutôt, c’est que tous les navigateurs sauf Internet Explorer appliquent la première règle, et qu’Internet Explorer – et lui seul – applique la seconde.

La stratégie couramment adoptée pour y arriver consiste à mettre la seconde règle en premier, puis à cacher l’autre à Internet Explorer en utilisant une syntaxe qu’il est seul à ne pas comprendre. Il y a plusieurs façons d’y arriver, mais quelle que soit l’astuce utilisée, on court toujours le risque qu’elle ne fonctionne plus comme prévu – voire même plus du tout – dans les versions de navigateur à venir.

Appeler une feuille de style dédiée à Internet Explorer

La meilleure et la plus sûre manière de procéder consiste à mettre la règle écrite pour Internet Explorer dans une feuille de style qui lui sera destinée en propre, et d’appeler cette feuille de style au moyen d’un commentaire conditionnel que seuls les navigateurs IE peuvent comprendre.

Il faut mettre le code suivant dans un fichier que l’on nommera, par exemple, ie.css :

div#hdp img {
     border:0; 
     position:relative; 
     top:-4em; 
     right:25px; 
     float:right;
}

puis appeler ce fichier grâce à la ligne de code HTML que voici :

Revenez! Inutile d’avoir peur, ça ne mord pas. Après quelques explications, vous verrez, tout sera beaucoup plus clair.

Comme tout commentaire HTML, cette ligne de code débute et se termine par , respectivement. Or les navigateurs et autres agents-utilisateurs sont normalement conçus pour ignorer ce qui se trouve à l’intérieur de ces deux expressions.

Là où ça devient intéressant pour nous, c’est que dans certains cas de figure bien précis, le contenu d’un commentaire sera non plus ignoré, mais interprété par Internet Explorer. Il sera même possible de préciser par quelle(s) version(s) d’Internet Explorer le code sera interprété et par quelle(s) autre(s) ignoré. Le plus beau, c’est que cette possibilité ne se fonde pas sur un bogue, mais sur un fonctionnement prévu et délibéré d’Internet Explorer.

Coupons maintenant notre ligne de code en trois parties, comme ceci :

Avec cette disposition, on voit plus clairement la manière dont les commentaires conditionnels sont organisés. On a, au milieu, du code HTML normal, et autour, des instructions que seul Internet Explorer est conçu pour comprendre.

La ligne du milieu comprend le code HTML normal pour appeler la feuille de style ie.css. Parce qu’il est inclus dans un commentaire conditionnel, ce code sera totalement ignoré des navigateurs autres que Internet Explorer et c’est exactement ce que nous voulons.

Grâce aux instructions [if IE] et [endif], Internet Explorer comprendra qu’il s’agit d’un commentaire conditionnel et, donc, qu’il doit non pas ignorer, mais interpréter le code HTML qui s’y trouve. En précisant [if IE lte 6], où « lte » vaut pour « less than or equal to », on spécifie au navigateur que seules les versions d’Internet Explorer égales ou inférieures à 6 doivent se comporter ainsi. Les autres passeront outre. C’est donc dire que ce commentaire n’aura aucune incidence sur un éventuel Internet Explorer 7, 8 ou 9.

En somme :

  1. s’il s’agit d’un navigateur autre que IE, le contenu du commentaire sera totalement ignoré;
  2. s’il s’agit d’Internet Explorer et que la version du navigateur est égale ou inférieure à 6, le contenu du commentaire sera non pas ignoré, mais interprété;
  3. s’il s’agit d’Internet Explorer et que la version du navigateur est supérieure à 6, le contenu du commentaire sera totalement ignoré.

Conclusion

HTML


  [...]
  
  

CSS

Contenu du fichier normal.css :

div#hdp img {
     border:0; 
     position:fixed; 
     top:300px; 
     right:25px;
}

Contenu du fichier ie.css :

div#hdp img {
     border:0; 
     position:relative; 
     top:-4em; 
     right:25px; 
     float:right;
}