Astuces - Web - positionnement - chp. 1

Centrer un élément

Le comment du pourquoi :

On rencontre très souvent sur des forums d'aide la question :
- « Comment centrer mon contenu horizontalement et verticalement ? ».
Très souvent (trop) il a été proposé la solution de la balise table avec pour attribut valign="middle" et align="center" sur le td.

Cette technique certes fonctionnelle, n'est pas à encourager, pour des raisons de sémantique/accessibilité. En effet un tableau n'est pas destiné à faire de la mise en page.
De plus immaginez l'effet au niveau d'un navigateur vocal ? (qui lit chaque cellule).

Enfin cette technique peut s'avérer très (très) lourde et difficile d'entretien.

Centrer à l'aide d'un tableau

Visuel :

Exemple de centrage avec tableau

Sources :

CSS :
html , body{
margin:0; padding:0;
height:100%; /* FF - IE7 */
overflow:auto; /* Cache les barres de scroll si non utile - IEx */
}

#bodyConteneur{ /* Tableau de centrage */
width:100%; height:100%;
}

#siteConteneur{
width:500px; height:300px; /* Dimensions désirées pour le site */
border:1px solid blue;
text-align:left; /* Rectifie l'alignement du texte forcé par le TD */
}
HTML :
<table id="bodyConteneur">
<tr>
<td valign="middle" align="center">
<div id="siteConteneur">
<h1>Mon site</h1>
<p>
blablablablablabla blablablabla blabla blablablablablablablabla blablablabla<br />
blablablablablablablablablabla blablablablablabla blablablablablablablabla
</p>
</div>
</td>
</tr>
</table>

Vous pouvez constater de la lourdeur du code et que cela peut devenir rapidement complexe au niveau suivit.

:: Remonter ::

Uniquement via CSS

Problèmes :

Si le navigateur dispose d'une résolution inférieure au contenu du site, des "parties" du site seront inaccessibles.
En cas de redimensionnement du navigateur, même problème que ci-dessus.
Implique l'utilisation de dimension fixe (px) pour le contenu du site (possible en dimension relative mais plus compliqué).

Avantages :

Simplicité de mise en oeuvre, fonctionne même si JavaScript est désactivé (normal ça n'en utilise pas :-) )

Explications :

On utilise un conteneur pour tout le site.
Celui-ci sera positionné via CSS en position:absolute;, le rendant ainsi indépendant de la page.
Ce même conteneur, se voit attribuer un positionnement à 50% du haut et 50% de la gauche (centre du navigateur).
Le problème là est que le coin supérieur gauche du site commence à partir de ce point central, on est pas dans le but recherché :-).
L'astuce réside, dans l'utilisation de marge négative et la connaissance des dimensions "hors tout" du site.
Prenons les dimensions de l'exemple précédent, soit 500 pixels en hauteur et 300 pixels en largeur.
La moitié de ce site se situe donc à 250 pixels du haut et 150 pixels de la gauche. Nous pouvons donc voir qu'il suffit de "reculer" et "remonter" le site de ces valeurs pour le centrer correctement.
Démonstration faite par l'exemple ci-dessous.

Visuel :

Exemple de centrage avec CSS

Sources :

CSS :
html , body{
margin:0; padding:0;
overflow:auto; /* Cache les barres de scroll si non utile */
}

#siteConteneur{
position:absolute; top:50%; left:50%;
margin-left:-250px; /* positionnement gauche : width/2 */
margin-top:-150px; /* positionnement haut height/2 */
width:500px; height:300px; /* Dimensions désirées pour le site */
border:1px solid blue;
}
HTML :
<div id="siteConteneur">
<h1>Mon site</h1>
<p>
blablablablablabla blablablabla blabla blablablablablablablabla blablablabla<br />
blablablablablablablablablabla blablablablablabla blablablablablablablabla
</p>
</div>

la simplicité du code parle pour elle :-).

:: Remonter ::

CSS et JavaScript

Problèmes :

Si votre visiteur désactive JavaScript sur son navigateur, il n'y aura pas de centrage vertical.

Avantages :

Quelque soit la définition de l'écran du visiteur ou si celui-ci redimensionne son navigateur, vous êtes certain que votre site restera accessible. Quoi qu'il arrive le site est centré à l'horizontal.

Explications :

Nous aurions pu reprendre la technique du centrage via CSS du moins en partie mais nous allons utiliser un "mixage".
Tout dabord nous allons centrer le site à l'horizontal et ce uniquement via CSS avec une technique qui ne posera pas de problème, même en cas de redimensionnement du navigateur.

Centrer horizontalement via CSS

Il nous suffit de créer un premier conteneur (*bodyConteneur* en bordure rouge dans l'exemple), celui-ci sera de la largeur totale du navigateur, soit 100%. Ensuite à l'intérieur de celui-ci nous créons un second conteneur (*siteConteneur*), qui contiendra notre site.
L'astuce réside à mettre le premier conteneur avec l'attribut CSS : text-align:center; pour IE (5.5->7) afin de centrer le second conteneur. Et d'ajouter l'atribut margin:0 auto; pour le second conteneur afin qu'il se centre de lui-même pour FF.
Cette technique est `normalement` compatible pour tous les navigateurs.

Petit inconvénient de cette technique, le conteneur de niveau 1 étant à text-align:center; tous les éléments enfants seront centrés, il faut donc penser à rétablir le flux.
Pour ce, il suffit de faire un text-align:left; sur le second conteneur... Mais on se retrouve dans le même problème que le cas précédent.. Si on utilise des balises HTML qui centre automatiquement le contenu, celui-ci sera aligné à gauche ... À vous de voir au mieux ;-).

Visuel :

Exemple de centrage horizontal avec CSS

Sources :

CSS :
html , body{
margin:0; padding:0;
height:100%;
overflow:auto; /* Cache les barres de scroll si non utile */
}

#bodyConteneur{
width:100%;
text-align:center; /* Centrer horizontalement pour IEx */

/* Permet de visualiser le conteneur - Retirer les 2 lignes suivantes */
margin-left:-2px;
border:1px solid red;
}

#siteConteneur{
margin:0 auto; /* Centrer horizontalement pour FF */
width:500px; height:300px; /* Dimensions désirées pour le site */
border:1px solid blue;
}
HTML :
<div id="bodyConteneur">
<div id="siteConteneur">
<h1>Mon site</h1>
<p>
blablablablablabla blablablabla blabla blablablablablablablabla blablablabla<br />
blablablablablablablablablabla blablablablablabla blablablablablablablabla
</p>
</div>
</div>

:: Remonter ::

Centrer verticalement via JavaScript

Nous reprenons le code ci-dessus, et nous lui ajoutons quelques modifications.

  1. Nous rendons le premier conteneur indépendant (position:absolute;) en profondeur 2 (z-index:2;)
  2. Nous ajoutons une image transparente de 1 pixel par 1 pixel à 100% de hauteur que nous rendons indépendant (position:absolute;) en profondeur 1 (z-index:1;)
  3. Nous utilisons un script JavaScript, qui va analyser la hauteur de cette image et calculer la hauteur disponible en temps réel dans votre navigateur.
  4. Le script JavaScript va recalculer la marge négative du conteneur principal

Visuel :

Exemple de centrage horizontal + vertical avec CSS et JS

Sources

CSS :

Il suffit d'ajouter les lignes suivantes au CSS de *bodyConteneur* et le CSS pour l'image transparente.

#bodyConteneur{
position:absolute; top:0; z-index:2; /* Rendre le conteneur principal indépendant */
...

}

/*
Positionne l'image dans le coin gauche supérieur du navigateur
Lui affecte une hauteur égale à la hauteur totale disponible
Nota : le z-index à 1, place l'image sous le site
*/
#sizeWindow{
position:absolute; top:0; left:0; z-index:1;
width:0; height:100%;
}
HTML :

On ajoute l'image à la fin du code HTML

<div><img src="images/spacer.gif" id="sizeWindow" alt="" /></div>

Vous allez vous dire : "mais on se retrouve quasi dans le même cas de figure que l'exemple précédent ?!?" (Uniquement via CSS).
C'est pas finit !!!! :-)

Nous allons à présent utiliser un ensemble de fonctions JavaScript.
- Un ensemble de fonctions qui permettent de trouver un élément par son id et des informations sur celui-ci (ça pourra toujours vous servir ;-) )
- Une fonction qui "recalcule" le positionnement de *bodyConteneur*
- Une fonction qui se lance au chargement de la page
- Une fonction qui se lance au redimensionnement du navigateur

Ces fonctions seront à mettre dans l'ordre dans votre fichier JavaScript (ex : putInMiddle.js)

JavaScript - fonction 1 :
// Permet de trouver tout élément par son ID
function Ident(Obj){ return (document.all)?document.all[Obj]:document.getElementById(Obj); }

// Permet de trouver la position X d'un élément
function posX(Obj){ return (Obj.offsetParent)?(Obj.offsetLeft + posX(Obj.offsetParent)):(Obj.offsetLeft); }

// Permet de trouver la position Y d'un élément
function posY(Obj){ return (Obj.offsetParent)?(Obj.offsetTop + posY(Obj.offsetParent)):(Obj.offsetTop); }

// Permet de trouver la largeur d'un élément
function posW(Obj){ return (Obj.offsetParent)?(Obj.offsetWidth + posX(Obj.offsetParent)):(Obj.offsetWidth); }

// Permet de trouver la hauteur d'un élément
function posH(Obj){ return (Obj.offsetParent)?(Obj.offsetHeight + posY(Obj.offsetParent)):(Obj.offsetHeight); }
JavaScript - fonction 2 :
// Centrage du site en hauteur
function putInMiddle()
{
var hauteurNavigateur = posH( Ident( 'sizeWindow' ) );
var hauteurSite = posH( Ident( 'bodyConteneur' ) );
var milieuSite = parseInt( hauteurSite / 2 );
// Calcul de la marge du haut
var newMargin = parseInt( ( hauteurNavigateur - hauteurSite ) / 2 ) ;

// le site est plus grand que le navigateur - pas de centrage vertical
if( newMargin <= 0 )
{
Ident( 'bodyConteneur' ).style.top = '0';
Ident( 'bodyConteneur' ).style.marginTop = '0';
}
// le site est moins grand que le navigateur - centrage vertical
else if( posY( Ident( 'bodyConteneur' ) ) <= 0 )
{
Ident( 'bodyConteneur' ).style.top = '50%';
Ident( 'bodyConteneur' ).style.marginTop = '-' + milieuSite + 'px';
}
}
JavaScript - fonction 3/4 :
// lancement du script au chargement
window.onload = function(){ putInMiddle(); }

// lancement du script au redimensionnement
window.onresize = function(){ putInMiddle(); }

Voilà, il ne vous reste plus qu'à soit inclure cette série de fonction dans un fichier et charger celui-ci dans la partie <head></head> de votre site via :

<script type="text/javascript" src="putInMiddle.js"></script>

Soit en l'insérant directement sur votre page (toujours dans <head></head>), via :

<script type="text/javascript">
/* <![CDATA[ */

... Votre script JavaScript ...

/* ]]> */
</script>

Bonne dev' :-).