Niveau Niveau confirmé

Initiation au positionnement CSS (partie 2)

Tutorielcss

Publié par le , mis à jour le (611201 lectures)

css float position absolute relative flux flottant positionnement

Le positionnement des éléments en CSS est sans aucun doute l'un des aspects les plus intéressants de cette technologie, mais également l'un des plus ardus. Positions, flux et autres flottants sont pourtant des notions essentielles à une bonne maîtrise de la mise en page. Si de plus en plus d'intégrateurs semblent aujourd'hui acquérir les bases du comportement de ces propriétés, les choix des techniques demeurent couramment discutables, tout au plus hasardeux. Voyons ces méthodes de positionnement en détails afin de ne plus se laisser aller à des choix arbitraires incohérents.

Partie 2

Sommaire du document

  1. Parce qu'une révision des bases ne fait jamais de tort…
  2. Que choisir dans mon cas?
  3. En guise de conclusion

Parce qu'une révision des bases ne fait jamais de tort…

La section qui suit se contente d'introduire brièvement les notions de positionnements disponibles en CSS. Pour ceux qui ne se sentent pas à l'aise avec ces différentes notions, je ne saurai que trop insister sur l'importance de jongler avec ces différentes facettes du placement des éléments. De nombreuses références existent en français, dont:

Notion de flux

Le flux d'un document pourrait se définir comme étant le comportement naturel d'affichage des éléments d'une page web. Autrement dit, les éléments se succèdent dans l'ordre où ils sont déclarés dans le code HTML. Grossièrement, les éléments de séquençage, tels que h1, p ou ul, s'affichent logiquement par défaut les uns en-dessous des autres tandis que les éléments délimitant pour la plupart des portions de textes dans un but de gain sémantique s'affichent côte à côte. Nos deux groupes d'éléments peuvent être classés en deux familles:

  • Les éléments de type block (h1, p, ul, ol, dl, table, blockquote, etc.)
  • Les éléments de type inline (a, img, strong, abbr, etc.)

Un élément de type block peut s'identifier à une brique, à un gros "bloc" d'informations qu'on va pouvoir manipuler aisément. Il se différencie des éléments de type en ligne sur différents points, dont ceux-ci :

  • Il occupe l'entierté de la largeur de son conteneur
  • Il permet l'attribution de marges verticales
  • Il permet la modification de sa hauteur et largeur

Le premier point est primordial, nous utiliserons abondamment ce comportement par défaut bien pratique dans la création de nos mises en page. Notons également que tout élément peut être "reclassé" dans la famille opposée grâce à la propriété display.

Il faut garder à l'esprit qu'un élément dans le flux sera toujours plus simple à manipuler et plus flexible dans sa relation aux autres éléments. Gardez en tête que laisser à un élément son comportement naturel est toujours à privilégier. Autrement dit, on ne sortira un élément du flux que lorsqu'on ne pourra pas faire autrement. Bien entendu, le flux montre rapidement ses limites lorsqu'on envisage une mise en page un peu sophistiquée…

Revenir au sommaire

La propriété position

La propriété position porte merveilleusement bien son nom puisqu'elle va nous permettre de gérer les… positions. C'est la propriété vers laquelle l'on se doit de se tourner en premier lieu dès que l'on considère une mise en page pour laquelle les possibilités du flux ne suffisent plus, et c'est là toute la raison d'être de cette puissante propriété.

La position relative

La position relative (position:relative) permet de décaler un élément par rapport à une position de référence: celle qu'il avait dans le flux. Les éléments qui le suivent et le précèdent ne sont pas influencés par ce décalage puisqu'ils considèrent que l'élément est toujours dans le flux à sa position initiale. En pratique, ce comportement est rarement recherché bien qu'il puisse s'avérer utile dans certains cas.

Attribuer à un élément une position relative peut par contre être pratique, voire indispensable, dans d'autres situations dont les plus courantes sont sans nul doute les suivantes:

  • Servir de référent à un élément enfant positionné en absolu (rappelons qu'un élément positionné absolument grâce aux propriétés top, left, … le fera par rapport à la fenêtre du navigateur à défaut d'avoir un parent lui-même positionné)
  • Bénéficier de la possibilité d'utiliser la propriété z-index pour gérer des superpositions d'éléments (propriété inopérante pour des éléments du flux)
La position absolue

La position absolue (position:absolute) permet de ne pas dépendre de l'ordre dans lequel les éléments HTML sont déclarés dans le code, contrairement aux flottants que nous verrons plus tard.

La position absolue s'affranchit définitivement du cordon liant jusqu'alors intimement contenu et présentation. L'élément étant totalement extrait du flux, il ne dépend plus du tout des éléments qui le côtoient. Il faut voir le positionnement absolu comme étant une méthode radicale (mais puissante) qui retire tout à fait un élément du flux: il n'existe pour ainsi dire plus aux yeux des éléments qui, eux, restent dans le flux.

Rappelons un point important concernant ce mode de positionnement : un élément positionné en absolu se réfère non pas à son parent direct, mais au premier ancêtre positionné qu'il rencontre.

L'élément, n'étant plus dans le flux naturel, perd une de ses caractéristiques majeures qui est celle de recouvrir la totalité de la largeur disponible de l'élément parent.

Il est capital de noter qu'un élément bénéficiant d'une position absolue ne bougera pas de sa position initiale tant que l'une des propriétés top, bottom, left ou right n'a pas été précisée; il s'agit d'ailleurs là d'un comportement appliquable à toutes les positions.

La position fixe

Le positionnement fixe (position:fixed) s'apparente au positionnement absolu, à l'exception des points suivants:

  • Lorsque le positionnement est précisé (top, right, …), l'élément est toujours positionné par rapport à la fenêtre du navigateur
  • L'élément est fixé à un endroit et ne pourra se mouvoir, même lors de la présence d'une barre de défilement. En d'autres termes, la position intiale est fixée au chargement de la page, le fait qu'une éventuelle scrollbar puisse être utilisée n'a aucune influence sur le positionnement de l'élément: il ne bouge plus de la position initialement définie.
La position statique

La position statique (position:static) correspond simplement à la valeur par défaut d'un élément du flux. Il n'y a que peu d'intérêt à la préciser, si ce n'est dans le but de rétablir dans le flux un élément en particulier parmi une série qui serait positionnée hors du flux.

Revenir au sommaire

La propriété float

La propriété float demeure sans doute, malgré des qualités intrinsèques évidentes, la propriété la plus mal comprise mais surtout, la plus mal employée des CSS. Sa simplicité d'utilisation apparente recèle pourtant certaines subtilités fondamentales et lui confère malheureusement un choix inconsciemment systématique pour toute disposition d'éléments en plusieurs colonnes.

Rôle & détournement des flottants

La propriété float existe avant tout pour répondre à un besoin typographique précis: la création d'habillages. Un habillage est une pratique courante dans le média print consistant à "enrouler" un texte autour d'un élément (graphique ou texte); il était normal de retrouver cette ouverture de mise en page dans notre média favori.

À l'instar du positionnement absolu, un élément flottant adopte par défaut la largeur qu'occupe son contenu. Le principe de base est simple: un élément flottant est ôté partiellement du flux et placé à l'extrême gauche (float:left) ou droite (float:right) de son conteneur, forçant par la même occasion tout contenu du flux qui suit à l'envelopper. Deux objets flottants dans la même direction se rangeront côte à côte, seul un contenu demeuré dans le flux qui les succède immédiatement initiera l'habillage. C'est justement ce caractère hâtif de disposition adjacente de blocs qui est la cause d'une mauvaise et sur-utilisation de cette propriété trop souvent écartée de son application originale.

Nettoyer les flottants

La propriété clear s'utilise conjoitement aux float et permet à un élément (qui peut être d'ailleurs lui-même flottant) de ne plus subir le comportement d'habillage dicté par un objet flottant qui le précède directement et, par conséquent, de se caler en-dessous de ce dernier. Le clear autorise un nettoyage des flottants exclusivement à gauche (clear:left), à droite (clear:right) ou les deux simultanément (clear:both).

Revenir au sommaire


Que choisir dans mon cas?

C'est en effet une question récurrente parfaitement légitime tant CSS nous permet d'aborder un même problème sous de nombreux angles. Essayons d'aborder différents cas-types et les solutions qui s'y prêtent le mieux.

Mise en page centrée en 2 colonnes, header et pied de page

Voici le style de résultat recherché:

Schéma: structure en 2 colonnes avec en-tête et pied de page

Voici notre structure HTML:

<div id="conteneur">
	<div id="header">
		<!-- Ceci est mon haut de page -->
	</div>
	<div id="sidebar">
		<!-- Ceci est ma colonne latérale -->
	</div>
	<div id="contenu">
		<!-- Ceci est mon contenu principal -->
	</div>
	<div id="footer">
		<!-- Ceci est mon pied de page -->
	</div>
</div>

Deux cas de figures se présentent:

  1. Je suis certain que ma colonne de gauche sera toujours plus courte que mon contenu principal
  2. J'ignore quelle sera la colonne la plus haute

Lorsqu'on se trouve dans la première situation (que je crois plus fréquente), c'est naturellement vers la propriété qui est censée gérer tout positionnement que l'on va se tourner. En gardant bien en tête les notions de flux, il nous sera très facile de réaliser cette mise en page rapidement:

#conteneur {width:760px; margin:0 auto;}
#sidebar {position:absolute; width:170px;}
#contenu {margin-left:170px;}

Que se passe-t-il exactement? Le fait d'attribuer une position absolue à notre colonne latérale la retire totalement du flux, l'élément "n'existe" plus aux yeux des autres éléments du flux. L'élément étant déjà à la bonne place, je n'ai pas à lui attribuer de coordonnées. Puisque cet élément est comme absent de la page du point de vue du div#contenu, celui-ci remonte jusqu'au premier contenu dans le flux qu'il rencontre, à savoir notre haut de page. Mon contenu étant un élément de type block, il recouvre par définition toute la largeur de #conteneur. Il ne reste plus alors qu'à lui attribuer une marge à gauche correspondant à la taille de ma colonne latérale.

Malheureusement, si nous nous trouvons dans le second cas évoqué (hauteurs imprévisibles), la propriété position ne pourra plus être employée sous peine de voir notre pied de page se placer juste en-dessous du header. En effet, nous n'avons sorti du flux dans l'exemple précédent que la colonne la moins haute, ce qui a pour effet de laisser le pied de page se placer naturellement sous le dernier contenu du flux rencontré: notre contenu principal. Si l'on ne peut prédire quelle sera la colonne la plus haute, il nous est forcémment impossible de garder avec certitude la bonne colonne dans le flux. Dans ce cas, et uniquement dans ce cas, nous allons recourir aux flottants avec parcimonie et être contraints de rajouter une division dans notre code HTML afin d'englober l'enfant flottant. Le code HTML se présente dès lors comme ceci:

<div id="conteneur">
	<div id="header">
		<!-- Ceci est mon haut de page -->
	</div>
	<div id="wrap">

		<div id="sidebar">
			<!-- Ceci est ma colonne latérale -->
		</div>
		<div id="contenu">
			<!-- Ceci est mon contenu principal -->
		</div>
	</div>
	<div id="footer">
		<!-- Ceci est mon pied de page -->
	</div>
</div>

La mise en forme CSS ne se contentera de sortir du flux que l'élément qui le demande obligatoirement:

#conteneur {width:760px; margin:0 auto;}
#wrap {overflow:hidden;}
#sidebar {float:left; width:170px;}
#contenu {margin-left:170px;}

Nous pouvons maintenant être assurés que notre pied de page se trouvera toujours après les deux colonnes, quelles que soient leurs hauteurs. Cependant, cette solution ne devrait être envisagée que dans ce cas précis d'inconnue totale de quantité de contenu, puisque:

  • Nous détournons une propriété de son rôle initial
  • Nous alourdissons notre code HTML uniquement à des fins de mise en forme
  • Nous rajoutons une ligne supplémentaire dans notre feuille de style pour créer le contexte de formatage

Revenir au sommaire

Quatre colonnes fluides de même hauteur centrées horizontalement

Nous allons réaliser une page listant les offres commerciales proposées par une société pour aboutir au résultat suivant:

Capture d'écran: structure à quatre colonnes de même hauteur

Nous sommes assurés que la dernière colonne sera toujours la plus haute: il est logique que le service le plus complet dispose de plus de fonctionnalités. Il faut que l'ensemble couvre toujours 80% de la largeur de la page et que toutes les colonnes fassent la même hauteur (celle de la dernière en l'occurence) pour éviter un effet d'escalier disgracieux. On pourrait penser à l'utilisation de la méthode dite des colonnes factices, mais elle se heurte à deux inconvénients, dont un majeur:

  • Les 4 colonnes étant fluides, il sera donc impossible de se servir d'une image pour simuler le colonnage extensible
  • Elle force l'auteur à recréer une image pour chaque changement de couleur voulu

Heureusement, la souplesse des positions nous permet de réaliser notre maquette aisément. Voyons d'abord notre structure HTML:

<h1>Des solutions adaptées à vos besoins</h1>
<ol>
	<li id="decouverte">
		<h2>Offre "Découverte"</h2>
		<p>
			Cette offre de bienvenue vous donne accès
			aux principales fonctionnalités du système:
		</p>
		<ul>
			<li>Tout le catalogue disponible</li>
			<li>Service accessible 24h/21</li>
		</ul>
	</li>
	<li id="start">
		<h2>Offre "Start"</h2>
		<p>
			Cette offre d'entrée de gamme vous donne accès
			aux principales fonctionnalités du système ainsi
			que quelques bonus:
		</p>
		<ul>
			<li>Tout le catalogue disponible</li>
			<li>Service accessible 24h/21</li>
			<li>Pas de frais d'activation</li>
			<li>Interface entièrement personnalisable</li>
		</ul>
	</li>
	<li id="services">
		<h2>Offre "Services+"</h2>
		<p>
			Cette offre très prisée vous donne accès
			aux principales fonctionnalités du système
			et aux nombreuses possibilités de partage:
		</p>
		<ul>
			<li>Tout le catalogue disponible</li>
			<li>Service accessible 24h/21</li>
			<li>Pas de frais d'activation</li>
			<li>Interface entièrement personnalisable</li>
			<li>Possibilité de téléversement</li>
			<li>Diffusion et stockage</li>
		</ul>
	</li>
	<li id="power">
		<h2>Offre "PowerUser"</h2>
		<p>
			Cette offre vous donne accès à l'ensemble
			des fonctionnalités du système pour une expérience
			utilisateur supérieure, avec entre autres:
		</p>
		<ul>
			<li>Tout le catalogue disponible</li>
			<li>Service accessible 24h/21</li>
			<li>Pas de frais d'activation</li>
			<li>Interface entièrement personnalisable</li>
			<li>Possibilité de téléversement</li>
			<li>Diffusion et stockage</li>
			<li>Création personnalisée de bibliothèques</li>
			<li>Espace alloué illimité</li>
			<li>Nombre d'alias illimté</li>
			<li>… et bien plus encore!</li>
		</ul>
	</li>
</ol>

Qu'avons-nous à faire maintenant ? Nous savons qu'il ne faudra positionner absolument que les 3 premières colonnes, la dernière étant la plus fournie en contenu, sa place réside dans le flux. Nous savons également que la totalité des 4 colonnes doit recouvrir 80% de la page. Ce dernier point pourra être rapidement réalisé en appliquant simplement au conteneur de ces colonnes (l'élément ol) des marges latérales de 10%. Voici la structure principale, le reste ne relève que du cosmétique:

* {padding:0; margin:0;}
ol {position:relative; margin:0 10%; list-style:none;}
ul {list-style:inside;}
h1 {text-align:center;}
#decouverte,#start,#services {position:absolute; width:25%; height:100%;}
#start {right:50%;}
#services {left:50%;}
#power {margin-left:75%;}

Revenir au sommaire

Image & texte côte à côte

Je souhaite disposer sur un espace de 300px de large un bout de texte et une image côte à côte sur base du marquage HTML suivant:

<p>
	<img alt="" src="kiwiz.png" width="100" height="130" />
	Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
	do eiusmod tempor incididunt ut labore et dolore magna aliqua.
	Ut enim ad minim veniam, quis nostrud exercitation ullamco
	laboris nisi ut aliquip ex ea commodo consequat. Duis aute
	irure dolor in reprehenderit in voluptate velit esse cillum
	dolore eu fugiat nulla pariatur.
</p>

Le résultat auquel j'aimerais arriver sans avoir à modifier mon code HTML est le suivant:

Capture d'écran: colonne de texte aligné à droite avec une illustration sur la droite

À nouveau, grâce aux positions et aux propriétés du flux, je vais rapidement arriver au résultat escompté: il me suffira simplement d'utiliser ma boîte p comme référent pour positionner mon image en ayant préalablement réduit la zone où mon texte pourra s'étendre:

p {position:relative; width:180px; padding-right:120px; text-align:right;}
p img {position:absolute; right:0;}

Revenir au sommaire


En guise de conclusion

La disposition des éléments en CSS est définitivement l'un des aspects de ce langage les plus subtils et mal compris. En attendant une implémentation raisonnable des différentes possibilités du display, ce sont essentiellement les propriétés position et float qui feront office de ténors en la matière.

Il n'est pas toujours aisé dans un apprentissage comme celui du positionnement CSS de savoir pour quels choix opter et dans quels cas. Aussi, une marche à suivre simple pourrait être appliquée dans le choix d'une méthode à privilégier:

  1. Je laisse tant que faire se peut les éléments dans le flux et tire parti de ses bénéfices (décalages grâce aux marges, recouvrement par un bloc de toute la largeur d'un parent, etc.)
  2. J'ai besoin de sortir un élément du flux:
    1. Si j'ai le contrôle du contenu de ma page ou que je suis assuré que mon élément hors flux sera systématiquement moins long que ce qui demeure dans le flux, je privilégie la propriété adéquate: position
    2. Si je n'ai aucun contrôle fiable sur des longueurs de contenu totalement inconnues et variables, j'opte pour des placements à base de flottants exclusivement sur les éléments qui l'imposent

Nous voyons donc que le seul cas où l'utilisation de flottants pour créer du multi-colonnage est plus adaptée est lorsque nous ne pouvons prédire quelle sera la plus haute des colonnes et qu'à celles-ci succèdent d'autres contenus.

Utilisez à bon escient les outils dont vous disposez et n'optez jamais pour une solution sans en évaluer les avantages et inconvénients; la réflexion de structuration de l'information va au-delà d'un balisage sémantique…

Revenir au sommaire

Pour aller plus loin