Les bases du positionnement en CSS
Le positionnement visuel des contenus dans une page web a toujours suscité matière à réflexion, à polémique et souvent à faire émerger de nouvelles méthodologies, et approches. Pendant longtemps se fut l’affaire des tableaux, d’ailleurs, certains ont même encore du mal parfois à s’en défaire. Alors qu’aujourd’hui, pointent de plus en plus l’usage de nouvelles méthodes révolutionnaires dans le domaine, telles que les boites flexibles, les grids ou encore les templates. Nous allons prendre quelques instants pour revenir sur quelques concepts de base du positionnement en CSS.
Principe de fonctionnement
Le travail sur la mise en forme des contenus d’un site web doit se faire avec la plus grande des méthodologies, et ce pour plusieurs raisons : le fait de pouvoir permettre une meilleure évolutivité des modules, d’assurer une maintenance optimale, et de garantir une portabilité accrue. Pour des sites de volume moyen, ou à forte déclinaison de rendu, il est souvent préférable d’avoir recours à un préprocesseur CSS de type compass ou less. Un article sur l’utilisation des préprocesseur est en cours d’écriture. N’hésitez pas à nous relancer sur le sujet.
Les styles CSS doivent être découpés en plusieurs types de fichiers distincts (même si au final on les regroupe sur une seule source, afin de minimiser les requêtes client / serveur). Donc parmi ces divers fichiers, on retrouve :
- une feuille de réinitialisation
- les éléments communs et récurrents
- les feuilles adaptées aux divers supports (y compris celle de l’impression)
Layout vs Visuel
Avant de se lancer dans la gestion des détails et des points particuliers, il est important de s’assurer de la viabilité des interfaces, principalement de l’ossature du modèle de page, au sein des divers supports de lecture (écran, tablette, smartphone, impression…). Pour cela nous allons distinguer deux types de gestion CSS : au tout début de l’utilisation des CSS, les mises en page étaient majoritairement gérées par des tableaux, une distinction se faisait entre CSS et CSS-P pour Positionning. Aujourd’hui nous parlerions plutôt de layout.
Donc, mettons en place une approche uniquement basée sur le layout des blocs principaux de la page et assurons nous de leur bonne portabilité en RWD, que celui-ci soit fixe (adaptatif) ou liquide (responsive). De simple blocs, avec ou sans bordure et couleur d’arrière plan suffisent. Cependant, il est préférable d’avoir recours à des couleurs transparentes afin de mieux gérer les éventuelles superpositions.
Pour mettre en place cette première maquette, nous devons aborder deux notions fondamentales en CSS-P, le modèle de boite, et les divers outils de positionnement que nous avons à disposition. Ici encore, diverses approches sont possibles. Nous pouvons nous baser sur des frameworks CSS, et pour n’en citer que quelques exemples par type de famille :
- 960.gs, framework historique et divisible par 24, 20, 16, 12, 10, 8, 6, 4, 2… bref exploitable à toute les sauces,
- Golden Grid System, qui va se baser sur le nombre d’or (),
- Semantic Grid System, qui permet d’utiliser ses propres balises et non d’avoir recours à des push_8 col_4 qui sont moins explicites d’un point de vue sémantique,
- Grid System Generator, qui permet de construire son propre framework sur mesure
… ou, nous pouvons également tout créer depuis une page blanche. C’est au choix, et fonction de nos objectifs. Quoiqu’il en soit, il est toujours important, et intéressant de partir des bases et d’en décortiquer chacune des possibilités.
Quelle que soit la solution retenue, il est également important de créer une image d’arrière plan utilisant un mode grille ou tout type de papier millimétré, (pensez à l’améliorer de repères d’angle si des rotations sont envisagées, ou marquages quels qu’ils soient), ce qui nous aidera à positionner avec précision les différents éléments de la page. Du fait que cette image sera utilisée en background-image: url();
, il faut également penser, si l’on souhaite avoir une approche liquide (responsive), d’ajouter la propriété background-size: cover;
à la règle CSS qui gérera cet arrière plan, ainsi qu’une éventuelle notion de pattern, afin d’autoriser la cohérence de répétition de cet arrière plan repeat-x
et/ou repeat-y
.
Le modèle de boite
Fini l’époque du Doctype sniffing afin de s’assurer que le modèle de boite serait pris en compte en fonction du navigateur. Enfin… fini si vous développez pour des navigateurs Internet Explorer de versions supérieure à 6 (voir l’article . Les techniques et outils à disposition des standards du Web au chapitre Bascule sur DOCTYPE).
Depuis cette version, tous les navigateurs s’entendent haut et clair sur un modèle de boite identique. Ce modèle de boite est représentatif de tous les éléments balise de type bloc. Le plus simple reste un bon schéma, beaucoup plus parlant, explicite et représentatif ; Jetez un coup d’œil sur l’image agrandi pour mieux y voir… on comprend bien que par largeur, il faut bien entendre l’ajout complet des propriétés de dimensions de la boite :
largeur réelle de l'élément = padding-left + border-left + width + border-right + padding-right
A cet effet, si besoin est, il existe la propriété box-sizing
qui peut prendre les valeurs content-box
(par défaut, la valeur du modèle w3c) et border-box
. Cela permet, dans certaines situations, de pouvoir dimensionner des conteneurs, tout en leur appliquant bordures et remplissage, et surtout sans remettre en cause la disposition de la mise en page.
Une donnée importante à prendre en compte sur le modèle de boite, reste l’effondrement des marges. Lorsque deux blocs possédant des marges hautes et basses se suivent, l’espace entre les deux ne résultera pas de l’addition des marges, mais uniquement de la valeur de la marge la plus haute. Cette fonctionnalité est très utile, notamment pour le positionnement de paragraphes.
marge verticale entre éléments est différent de element.haut.margin-bottom + element.bas.margin-top marge verticale entre éléments est égale Math.max(element.haut.margin-bottom , element.bas.margin-top)
Le positionnement
Que la page et son contenu soit affichés dans un navigateur, sur une tablette, depuis un smartphone, ou disposés sur une feuille imprimée, ou bien encore visualisés depuis tout autre périphérique de sortie, il existe une manière pour positionner les éléments dans l’espace. Le flux normal, en se servant du modèle de boite, par flottement (float
), en jouant sur le multi-colonnes, en se servant de la propriété position (position
), ou de celle d’affichage (display flex
, inline-bloc
, table-cell
…) et de nouvelles à venir (grid
, templates
…)… un article sur le positionnement par flex-box
, grid
et templates
est en cours d’écriture. En attendant, regardons quelques uns des modèles énumérés ci-dessus.
Avant d’aller plus loin dans le positionnement, il est important de comprendre le flux par défaut d’un navigateur. Indépendamment de leur mode d’affichage (display
), les balises HTML sont réparties entre deux modèles, inline
et bloc
. Les balises de type bloc s’affichent en haut et à gauche, indépendamment de leur largeur (que celle-ci soit définie ou non), ils s’empilent les uns sous les autres et se comportent comme s’ils tenaient toute la largeur de la fenêtre. Les balises de type inline s’enfilent les unes à la suite des autres, (leur largeur ne pas être définie autrement que par l’élément parent qui les contient ou par le volume de leur contenu, et ce tant que la largeur de l’élément parent le permet. Une fois la largeur limite atteinte, l’élément passe et continu sur la ligne suivante.
Le positionnement par modèle de boite
C’est un des positionnement les plus classique. Il se base sur les divers propriétés margin
(top, right, bottom, left) et padding
(top, right, bottom, left) des éléments. Il est donc possible, sans sortir les éléments du flux, de les positionner en ajoutant des marges sur leur côté, et de les dimensionner par leur propriété width
, (attention, de penser à la propriété box-sizing
, voir plus haut sur le chapitre Le modèle de boite). Les éléments qui suivent s’adapteront à cette nouvelle occupation de l’espace. On peut donc utiliser des marges pour positionner les blocs entre eux et des espaces de remplissages pour adapter les marges intérieures auxquelles devront s’adapter les contenus.
Le positionnement par flottement
L’instruction float:left
ou float:right
, permet aux éléments affectés de devenir flottants. C’est-à-dire qu’ils sortent du flux et vont coller le bord spécifié contre l’élément précédent, à condition que l’espace disponible soit supérieur à la dimension de l’élément (dimension soit définie par width
ou par la largeur du contenu).
Du fait que l’élément sort du flux, et qu’il flotte, les éléments faisant partie du même conteneur parent et qui le suivent, vont également se mettre à flotter (voir les éléments <p> du second <article> flotaison.html). Si nous souhaitons arrêter ce flottement, non sollicité, il faut alors avoir recours à l’instruction clear:{left | right | both}
, en fonction du flottement en cours. Cette instruction va devoir se placer sur l’élément qui devra interrompre le flottement… seulement parfois, cet élément n’existe pas dans l’arborescence HTML. Il existe alors diverses solutions pour mettre en place cette mécanique, Force element to self-clear its children, How To Clear Floats Without Structural Markup (l’idée majeure reste de ne pas toucher à l’arborescence du HTML).
Une autre surprise inattendue apportée par les éléments flottants va être rencontrée sur la gestion du modèle de boite du conteneur parent. Étant donné que les éléments flottants sortent du flux, si l’élément conteneur parent ne possède pas de dimensions définies, l’habillage CSS de type bordure, fond de couleur… ne s’affichera pas correctement. Il faut forcer le moteur de rendu du navigateur à prendre en compte l’ensemble des éléments sortis du flux. La manière la plus simple et la plus directe est d’appliquer de l’instruction overflow:hidden
au conteneur parent. Cette instruction, demande de masquer les éléments qui dépassent de l’enveloppe. De ce fait, l’ensemble des éléments, flottants ou non, devront être interprétés pour calculer de manière implicite la hauteur du bloc. Du coup, l’habillage se fera correctement (voir les balises <article> dans flotaison.html).
Quelques fois, lorsque l’on travaille sur une composition avec deux ou trois colonnes, il peut être intéressant de placer certains éléments en flottaison gauche et d’autre en flottaison droite (tout en définissant des largeurs de distribution qui restent cohérentes). Voir l’exemple colonnes-float.html, où l’<article>
possède une largeur de 60% avec 5% de marge droite et flotte à gauche alors que la <section>
avec ses 35% de largeur flotte à droite (60 + 5 + 35 = 100%).
Le positionnement par propriété position
Comme son nom l’indique, la propriété position
permet de positionner les éléments avec précision, elle peut prendre quatre valeurs permettant de couvrir un large éventail de situations.
static
, l’élément reste dans le flux, il s’agit là de la valeur utilisée par les navigateur. Cependant, par défaut cette valeur n’est pas déclarée, ni même de manière implicite. Elle permet juste de pouvoir réinitialiser une valeur si besoin est,relative
, l’élément reste dans le flux, il se décale de sa position de base en fonction des valeurs définies partop
,left
,bottom
etright
(voir l’exemple, position-relative.html).absolu
, l’élément sort du flux et se positionne en fonction des valeurs définies partop
,left
,bottom
etright
en rapport de son premier parent positionné de manière explicite (voir l’exemple, position-absolute.html).fixed
, l’élément sort du flux et se positionne en fonction des valeurs définies partop
,left
,bottom
etright
en rapport de la fenêtre du navigateur.
Le positionnement par propriété display
Une autre possibilité pour gérer le positionnement réside dans le changement du mode d’affichage que le navigateur utilise. Par exemple, nous avons vu qu’il existait des éléments de type inline, et des éléments de type bloc, mais en réalité, la liste est plus complexe et complète que cela. Il existe également d’autres types, plus spécifiques, comme ceux adaptés aux éléments de liste, aux cellules de tableau, etc… Il est donc possible de rendre tout élément affichable selon ces modes… un exemple : prenons un simple élément <a>
, qui va donc s’afficher inline
, changeons sa propriété display:block
. Dorénavant la balise <a>
va s’afficher comme le ferait un élément de type block
, et du coup, on peut également agir sur la hauteur, les marges…
Il existe de nombreuses possibilités pour la propriété display
; inline
, block
, compact
, inline-block
, inline-table
, list-item
, marker
, run-in
, table
, table-caption
, table-cell
, table-column-group
, table-column-group
, table-footer-group
, table-header-group
, table-row
, table-row-group
, flex
, inline-flex
… Certaines comme flex
par exemple, feront l’objet d’un article spécifique, d’autres, comme les utilisations possibles de table-*
ou inline-block
, également.
Explorons deux trois situations avec des valeurs comme inline-block
, compact
, run-in
, table
, table-row
, table-cel
; qui vont permettre d’obtenir sensiblement le même résultat, à ceci près que les éventuelles marges ne sont pas gérées de la même manière. Imaginons un bloc de liste de la sorte :
<ul> <li> <h4Titre</h4> <p>Description du contenu...</p> </li> <ul>
Nous allons voir qu’il est possible de placer le titre <h4>
et la description <p>
sur la même ligne en utilisant simplement la propriété display. Cependant, il faut noter que tous les navigateurs peuvent ne pas être au rendez-vous.
inline-block | compact | run-in | table, table-row, table-cel | |
---|---|---|---|---|
Rendez vous sur la page de display.html et consultez le code adapté à chaque situation. |