"Position: fixed" chez IE

 

IE n'implémente pas la position fixed, on peut néanmoins l'obtenir grâce à la "propriété dynamique" expression() de Microsoft.

Alternative par manipulation de l'overflow :
(ne marche pas avec IE 5 et inf. ?)

Autre alternative : behavior:url();

 

Bloc fixed positionné par rapport au haut de page

La CSS classique :

<style type="text/css" media="screen">
selecteur { position: fixed; top: 0; left: 0; }
</style>

ne fonctionne pas avec IE.

 

Mais IE comprend :

selecteur { position: absolute; top: 0; left: 0; }

Simplement le bloc sélectionné sera positionné par rapport au haut de la page, non par rapport au haut de l'écran, et disparaîtra avec le scrolling. A moins que...

 

A moins que l'on puisse indiquer, pour la propriété top:;, une valeur variable selon le contexte, égale à la hauteur du scrolling (hauteur de la page au-dessus de l'écran).

 

Il est justement possible chez Microsoft d'indiquer une variable en lieu et place de la valeur d'une propriété. Quant à la valeur du scrolling, elle est disponible par "JavaScript".

 

expression() est une "propriété dynamique" de Microsoft qui va nous venir en aide, sous la forme :

top: expression(blabla JavaScript);

Par exemple, top: expression(10 + 10 + "px"); équivaut à top: 20px;

 

scrollTop est une propriété (MS) de l'objet body qui, sous la forme body.scrollTop donne la valeur verticale du scroll en pixel.

 

Ainsi, top: expression(body.scrollTop + "px"); donne à la propriété top la valeur du scrolling en pixel. C'est à dire que le bloc sélectionné s'affichera à cette valeur du haut du document, c'est à dire juste en haut de l'écran.

 

Résumons. La CSS suivante :

<style type="text/css" media="screen">
selecteur {
	position: absolute;
/*	top: expression(body.scrollTop + 20 + "px"); */
	top: expression(documentElement.scrollTop+body.scrollTop + 20 + "px"); /* Correction */
	left: 10px;
	}
</style>

affiche en permanence à 20 pixel du haut de l'écran et à 10 pixel du bord gauche. Ceci quel que soit le scrolling. C'est l'effet fixed obtenu chez IE.

 

Il reste encore des détails à régler !
- Tout d'abord lorsque l'on scrolle, le texte en fixed suit le document un bref instant avant de revenir à sa place, donnant un aspect saccadé désagréable.
- Deuxièmement il faut rajouter le code CSS destiné au fixed des autres navigateurs.
- On ne va pas se contenter d'un fixed positionné par rapport "au top". Nous verrons donc comment simuler un fixed / bottom.
- Mais voyons d'abord la question du DOCTYPE :

 

Déclaration de DOCTYPE et xml

Alors que le fixed de cette page marchait bien sous IE 5.5 et le DOCTYPE suivant :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
	"http://www.w3.org/TR/html4/loose.dtd">

cela se révèle ne pas marcher sous IE 6 ! Pourquoi ? Mystère !

Finalement ça marche en supprimant le DOCTYPE ou, ce qui revient au même, en le réduisant à ceci (Doctype incomplet à ne pas utiliser) :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

ou en mettant celui-la (qui permettra plus tard d'utiliser le sélecteur html[xmlns]) :

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"">

Pour pouvoir utiliser le Doctype strict et IE6 il faut ajouter "documentElement.scrollTop+" dans l'expression. (Cf correction)

 

Stabiliser le fixed

Pour éviter les saccades au scrolling, c'est très simple. Il suffit qu'il y ai dans la CSS un background en position fixed pour le body :

body { background: url(../jpg/galanthe.jpg); background-position: fixed; }

Le bouton "Accueil", en haut à gauche de la page, est ainsi réalisé. Vous pouvez constater sa parfaite stabilité au scrolling.

Plus simplement, il n'y a pas besoin d'un fichier image :

body { background: url(null) fixed ; }

(Mais dans ce cas le navigateur demande le fichier "null" au serveur, d'où une erreure 404 qui vient grossir les logs.)

 

Ajouter le code CSS des autres navigateurs

Lecteur pressé ?

Demander sur une même feuille de style à un navigateur d'être en position:absolute et aux autres d'être en position:fixed suppose de cacher à l'un ou aux autres une partie des "ordres". C'est là qu'interviennent des trucs ou "hacks".

Chaque hack a ses inconvénients qui compliquent bien la tâche...

 

selecteur {
	left: 10px;
	/* pour les navigateurs "normaux" */
	position: fixed;
	top: 50px;
	/* pour IE */
	_position: absolute;
	top: expression(body.scrollTop + 50 + "px")
	}

Ici, IE rencontrera deux valeurs successivement mais, comme il se doit, ne retiendra que la dernière. Etrangement il ignore l'underscore devant _position et admettra la valeur absolute. [The Underscore Hack]

Les navigateurs normaux rencontreront ici des propriétés inconnues d'eux et, comme il se doit, les ignoreront : _position avec l'underscore n'est pas correctement écrit et sera donc négligé. Seul position: fixed; sera retenu. De même les navigateurs autres qu'IE ignoreront expression(...) et délaisseront donc top: expression(...); au profit de top: 50px;

Le "truc" de l'underscore a des défauts : il ne marche pas avec IE Mac ! d'autre part, il donne une feuille de style qui ne passe pas au validateur (_position est incorrect)

 

Les puristes préférent d'autres trucs, comme le hack de Tantek Celik (mais ce hack ne marche pas avec IE 6 !) [The Tantek Celik hack / Bidouillage de Boîtes]:

#menufix { 
	left: 10px;
	/* pour IE */
	position: absolute;
	top: expression(body.scrollTop + 50 + "px")
	voice-family: "\"}\""; /* Tantek Celik hack. */
	voice-family: inherit;
	/* pour les autres navigateurs */
	position: fixed;
	top: 50px;
	}
/* "be nice to Opera 5" (pour certains navigateurs) */
html>body #menufix {
	position: fixed;
	top: 50px;
	}

L'accolade } contenu dans la valeur de voice-family:; fait croire indûment à IE 5 ou 5.5 que c'est la fin du bloc de déclaration. Il ne lit donc pas la suite.
Plus loin IE rencontre un sélecteur d'enfant >, ce qu'il ne comprend pas (IE 5 à 6) (IE est très imparfait !). IE n'interprétera donc pas le second bloc de déclaration. Au total IE n'aura vu que les deux lignes qui lui sont réservées, tandis que les autres lui sont cachées.

Les déclarations cachées à IE sont toutefois visibles par les autres navigateurs qui en tiendront compte puisque c'est toujours la dernière valeurs rencontrée qui est retenue.

 

Le hack de Tantek ne marchant pas sous IE 6 ni le hack de l'underscore sous IE Mac, on peut essayer ceci :

<style type="text/css" media="screen">
body { background: url(null) fixed ;}
#menufix { 
	left: 10px;
	position: absolute; /* pour IE : */
	top: expression(body.scrollTop + 50 + "px")
	}
html[xmlns] #menufix { position: fixed; top: 50px;} 
html>body #menufix { position: fixed; top: 50px;}
</style>

Les deux dernières lignes ne sont pas lues par IE.

html[xmlns] est lu par certains navigateurs. html>body permet encore de récupérer Opéra (6.05). Cependant, cela va certainement laisser de coté d'anciens navigateurs.

 

Hacks en vrac :

 

A défaut d'une solution CSS simple, on pourrait utiliser les conditional comments de MS qui permettent d'appliquer sélectivement une feuille de style à IE ou à une de ses versions (et qui sont ignorés des autres navigateurs) :

<style type="text/css">
selecteur { propriété: valeur1;}
</style>
<!--[if IE 5]>
<style type="text/css">
selecteur { propriété: valeur2;}
</style>
<![endif]-->

Ou encore sous cette forme

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

 

Bloc fixed positionné par rapport au bas de page

On peut rêver, mais bien entendu cela ne fonctionne pas avec IE :

selecteur { position: fixed; bottom: 0; left: 0; }

 

On imagine alors remplacer la valeur de bottom par expression() dans quelque chose du genre :

selecteur { position: absolute; bottom: 0; left: 0; }

 

Hum ! Avez-vous déjà vu comment IE se comporte dans ce cas de figure ? Je renonce à cette configuration.

 

Je poursuis donc avec la configuration utilisée plus haut, En modifiant la formule JavaScript, cela va sans dire.

<style type="text/css" media="screen">
selecteur {
	position: absolute;
top:expression(body.scrollTop + document.body.clientHeight - 25 + "px");
	left: 10px;
	}
</style>

document.body.clientHeight représente la hauteur de la fenêtre, en pixel. En l'ajoutant au scrolling on obtient la distance du haut du document au bas de l'écran. On affiche alors le haut du bloc sélectionné à cette distance du haut du document c'est à dire au bas de l'écran. En retranchant, comme ici, 25 pixels de cette distance, on affiche 25 pixel plus haut. (Si le bloc ainsi fixé déborde sous le bas de l'écran, il déborde encore quand on est en bas de la page et est responsable d'une possibilité de scroller "à blanc" une prolongation inexistante de la page.) Vous trouverez un exemple en bas à gauche de cette page.

 

Je vous laisse chercher vous même comment obtenir le même résultat avec les autres navigateurs.

 

 

web-jardin, Haut