CSS 3 - Le positionnement :

Introduction :

Nous avons vu au chapitre précédent le modèle de boîtes et plus particulièrement comment modifier la hauteur, la largeur, l'espacement de ces boîtes. Nous allons maintenant voir comment vont se positionner ces boîtes dans une page HTML et également comment intervenir sur ce positionnement.

Important

Même si tous les positionnements sont vus ici, concentrez-vous sur le positionnement flex qui est le plus récent et utile pour positionner les différentes zones de votre site.

En ligne et en bloc :

À l'origine en HTML4, on distinguait deux types de balises de structure : le type en ligne ou le type bloc.

Les éléments de rendu "bloc" servent à distinguer les parties entières de texte, comme des titres, des paragraphes, des listes, des citations, etc. Voici une liste des éléments de type bloc : div, p, h1 ... h6, ul, ol, table, pre, form, blockquote, etc.

Les éléments de type bloc se placent toujours l'un en dessous de l'autre par défaut. Par exemple : une suite de paragraphes (balise <p>) ou les éléments d'une liste (balise <li>). Par ailleurs, un élément de type bloc occupe automatiquement, par défaut, toute la largeur disponible dans son conteneur.

Les éléments de type en ligne se placent toujours l'un à côté de l'autre afin de rester dans le texte. Par exemple : la mise en évidence d'une partie de texte à l'aide de la balise <em>.

Prenons l'exemple d'une image qu'on insère dans un document (.doc) de Word (Microsoft), on peut choisir dans les propriétés de l'objet si on désire que l'image apparaisse dans le texte ou comme étant un élément séparé :

Une image insérée en ligne : Une image insérée comme un bloc :
Mon image apparaît dans le texte. exemple d'image en ligne Vous êtes bienvenus dans ce cours ! Mon image apparaît comme un bloc séparé.
exemple d'image en ligne
Vous êtes bienvenus dans ce cours !

Chaque navigateur possède une feuille de style par défaut dans lequel il définit l'affichage en bloc ou en ligne des éléments HTML. Voici donc une raison pour laquelle le rendu HTML pour différer d'un navigateur à un autre. Maintenant pour les éléments les plus courants, vous ne verrez pas de différence (ouf !), les paragraphes sont toujours affichés en bloc par défaut quel que soit le navigateur utilisé.

Important

Il faut savoir qu'en HTML5 le typage des éléments HTML en bloc ou en ligne n'est plus d'actualité. Le navigateur possède une feuille de style par défaut dans laquelle chaque élément HTML est défini en ligne ou en bloc ou encore en table via la propriété display (voir ci-dessous). Le développeur web, quant à lui, peut utiliser cette propriété pour modifier le comportement par défaut donné par le navigateur. Un élément HTML ayant donc un rendu par défaut en ligne peut très bien devenir un bloc et vice-versa.

Le positionnement des boîtes :

Pour afficher une page web, le navigateur interprète le flux des éléments de type bloc de manière séquentielle, c'est-à-dire du début à la fin du fichier HTML en les affichant au fur et à mesure, les blocs étant placés les uns en-dessous des autres, séparés par une ligne (fictive). Les éléments en ligne quant à eux sont placés à la queue-leu-leu sur la même ligne, selon leur ordre d'apparition.

Il est néanmoins possible de modifier cet affichage par défaut (statique) en spécifiant un positionnement différent : absolu (absolute), relatif (relative) ou fixe (fixed). Dans chacun de ces modes, le positionnement de la boîte peut être spécifié pour l'un ou l'autres des côtés : top (côté supérieur de la boîte par rapport au côté supérieur de l'élément de référence), bottom (côté inférieur), right (côté droit) et left (côté gauche), l'élément de référence dépendant du type de positionnement. Il est déconseillé d'utiliser des valeurs négatives car certains navigateurs les interprêtes de manière personnelle.

La manipulation de ces positionnements peut être délicate car elle risque de produire des recouvrements de blocs.

Une autre manière de positionner des éléments d'une page HTML est d'utiliser le mode flottant (float) qui permet de construire des menus, de créer une colonne, etc.

Positionnement absolu (position: absolute) :

Le positionnement absolu est calculé à partir des côtés du document. Par exemple, la combinaison des propriétés CSS.

position: absolute; et left; 10%; va déplacer le bloc concerné par ce style par ce style de 10% par rapport au côté gauche du document.

Positionnement relatif (position: relative) :

De manière similaire, le positionnement relatif est calculé à partir de l'élément bloc précédent.

Positionnement fixe (position: fixed) :

Le positionnement fixe est calculé à partir du coin supérieur gauche de la fenêtre du navigateur.

Positionnement flottant (float: left; ou float: right;) :

Le positionnement flottant permet de modifier le positionnement statique des éléments pour "faire flotter" les éléments à gauche float: left; ou à droite float:right;.

Dans l'exemple suivant, l'image est positionnée à gauche.

Le CSS : L'affichage :
div#header {
    color: maroon;
    font-family: sans-serif;
    border-bottom: 1px solid black;
}
div#footer {
    color: black;
    clear: left;
}
div#texte {
    margin-left: 25%;
}
div#image {
    background-color: red;
    float: left;
    width: 20%;
}
saisie écran encadrement

Dans cet exemple,

  • La propriété float: left; de l'élément image indique que l'élément doit être flottant à une gauche et placé hors du flux normal; il est important de lui donner une dimension grâce à la propriété width: 20%; pour lui fixer une taille fixe, en rapport avec l'élément voisin.
  • La propriété margin-left: 25%; de l'élément texte est nécessaire pour permettre à l'élément flottant de trouver sa place à gauche de l'entièreté du texte.
  • La propriété clear: left; de l'élément footer signifie que l'élément reprend un position normale dans le flux.

En gros, l'utilisation de float: left; permet de retirer un élément du flux normal et ne sera aujourd'hui utilisé que pour placer un élément à gauche ou à droite avec les autres éléments "inline" qui se placent autour (imahe d'illustration dans un article par exemple).

Display :

En HTML5, nous retrouvons le typage d'éléments HTML en ligne et en bloc comme expliqué ci-dessus mais également d'autres typages que voici :

  • none : l'élément n'est pas affiché.
  • inline : l'élément est affiché en ligne.
  • block : l'élément est affiché en bloc.
  • inline-block : l'élément est affiché en ligne mais peut être redimensionné (width, height) comme un bloc.
  • list-item : l'élément est affiché en élément de liste (ex : <li>).
  • table : l'élément estaffiché comme une table (ex : <table>).
  • flex : l'élément est affiché comme élément flexible (voir ci-dessous).
  • grid : l'élément est affiché comme une grille (voir ci-desous).

Parmi tous les positionnements présentés ici, les trois positionnements les plus utilisés sont le inline-block et surtout le positionnement flex et/ou grid qui nous facilite grandement la tâche.

Positionnement inline-block :

Les manipulations que demande le positionnement flottant se révèlent parfois un peu délicates sur des sites complexes. Dès qu'il y a un peu plus qu'un simple menu à mettre en page, on risque d'avoir à recourir à des clear qui complexifient rapidement le code de la page. Imaginez que vous voulez réaliser une mise en page du type "menu à gauche suivi d'une partie centrale" (exactement comme la mise en page de ce syllabus). Dans ce cas, le positionnement inline-block convient parfaitement car :

  • Les éléments vont se positionner les uns à côté des autres (exactement ce qu'on veut pour placer notre menu et le corps de notre page !).
  • On peut leur donner des dimensions précises (là encore, exactement ce qu'on veut !).

Positionnement flex :

Important

Prenez la peine de découvrir et tester ce positionnement ! Vous pouvez facilement vous passer des autres positionnements mais pas de celui-ci.

Le dernier venu en terme de positionnement est le position flex. Celui-ci simplifie vraiment le positionnement de zones HTML.

Son principe est le suivant :

  1. Vous définissez un conteneur.
  2. Vous placez différents éléments à l'intérieur du conteneur.
  3. Vous renseignez à flex comment positionner ces éléments à l'intérieur du conteneur.

Exemple :

Le code : L'affichage :
<section id="monconteneur">
    <article>Élément 1</article>
    <article>Élément 2</article>
    <article>Élément 3</article>
</section>

#conteneur {
    display: flex;
}

Image issue de Open Classroom.

Quelques propriétés flex intéressantes :

  • flex-direction: column/row pour positionner les éléments verticalement ou horizontalement.
  • justify-content: space-around/space-between/center pour aligner les éléments sur l'axe princpal (horizontalement le plus plus souvent).
  • align-items: center/stretch/flex-start pour aligner les éléments sur l'axe secondaire (verticalement).
Important

Plus d'informations à ce sujet sur le site d'Open Classroom : Positionnement flex.

En gros, le display: flex permet de changer la disposition des élémentsavec un positionnementen ligne ou en colonne. Les éléments enfants d'une Flexbox ont alors la responsabilité de définir leur largeur/hauteur via les propriétés width/height via le flex-basis.

L'approche flexbox est donc utile pour changer la direction de placement des éléments (pour par exemple les placer les uns à côté des autres) sans forcément avoir de dimensions précises pour les enfants. On aura donc tendance à les utiliser dans les cas suivants :

  • On veut aligner les éléments verticalement ou horizontalement en insérant un espace avec la propriété gap.
  • On a une grille qui n'est pas uniforme (structure des colonnes qui varient entre chaque ligne).

Grid :

La grosse particularité du display: grid est le fait que l'élément parent a la responsabilité de définir la structure via un grid-template-columns ou grid-template-rows. Cela permet de ne pas avoir à ajouter des règle sur les éléments enfants.

Typiquement, comme son nom l'indique, ce type de positionnement est très adapté à une disposition en grille.

.grid {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(5, 1fr);
}

On peut aussi facilement créer une structure responsive qui adapte le nombre d'élément en fonction de la largeur souhaité pour les éléments.

.grid {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

On peut aussi utiliser ce type de disposition pour créer des structures de page rapidement grâce notamment au grid-area.

<style>
.layout {
    display: grid;
    min-height: 100vh;
    grid-template: "header header" min-content
                   "sidebar main" 1fr
                   "footer footer" min-content;
    grid-template-columns: 250px 1fr;
}
header {
    grid-area: header;
}
aside {
    grid-area: sidebar;
}
main {
    grid-area: main;
}
footer {
    grid-area: footer;
}
</style>
<div class="layout">
    <header>Header</header>
    <aside>Sidebar</aside>
    <main>Contenu</main>
    <footer>Footer</footer>
</div>

Cette approche permet de piloter facilement la structure depuis l'élément parent .layout en changeant le template via la propriété grid-template. Ce type de positionnement est donc intéressant pour les cas suivants :

  • On souhaite utiliser une grille simple.
  • On veut créer une structure qui peut être décomposer sous forme de colonnes (constantes entre chaque ligne).

En résumé, l'avantage d'utiliser des grilles CSS et des media queries pour faire la mise en page plutôt que d'utiliser un framework de type Bootstrap est multiple. Non seulement cela est plus green puisqu'il n'est pas nécessaire de charger le framework, mais cela permet de mieux séparer le font et la forme. Finie la litanie de classes associées à nos balises qui pollue le code HTML (exemple : <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2 col-xxl-1>). La mise en forme avec les grilles est intégralement gérée dans des fichiers CSS.

Exemple de fichier HTML :

<!DOCTYPE html>
<html lang="fr">
    <head>
        <title>Page de test avec une disposition utilisant une grille</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <link href="grid.css" rel="stylesheet">
        <meta name="description" content="Comment créer une page responsive sans utiliser de framework CSS">
    </head>
    <body>
        <header>
            partie en-tête...
        </header>
        <main>
            <article>
                <h1>Comment créer une page responsive sans utiliser de framework CSS</h1>
                <p>
                    Avec la propriété CSS Grid et des média queries !
                </p>
                <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Ipsum quis sed voluptas maxime voluptatibus illo deserunt temporibus pariatur accusantium commodi quidem similique rem natus nostrum odit officiis blanditiis reprehenderit, fugiat, sequi placeat error harum amet eligendi voluptate! Quasi nisi facilis praesentium est ex consectetur placeat corrupti quas voluptatem, quis id.</p>
                <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Eveniet est facilis harum nisi quo architecto doloremque, voluptate qui dolor porro, autem ab reprehenderit ducimus neque sint nobis ipsam recusandae odit, sequi nihil expedita. Eligendi itaque amet odio quisquam similique obcaecati!</p>
                <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero corporis voluptates atque, quos dignissimos dicta quod vitae! Enim at pariatur quae expedita sed hic perferendis mollitia autem, voluptates, sint dolorem?</p>
            </article>
        </main>
        <aside>
            partie complément...
        </aside>
        <footer>
            partie pied de page...
        </footer>
    </body>
</html>

Le fichier CSS associé :

body {
    background-color: #e06ed1;
    display: grid;
    margin: 0;
    grid-template-columns: 1fr;
    grid-template-areas:
        "entete"
        "contenu"
        "complements"
        "piedPage";
    grid-template-rows: 100px 1fr 100px 100px;
}
@media (min-width: 576px) {
    body {
        grid-gap: 10px;
        grid-template-columns: 1fr 250px;
    }
}
@media (min-width: 768px) {
    body {
        grid-template-columns: 742px 250px;
        justify-content: center;
    }
}
header, main, aside, footer {
    padding: 10px;
}
header {
    grid-area: entete;
    background-color: #bfe966;
}
main {
    grid-area: contenu;
    overflow-y: auto;
    background-color: lavander;
}
aside {
    grid-area: complements;
    background-color: mediumturquoise;
}
footer {
    grid-area: piedPage;
    background-color: #ebb2b2;
}

Dans cet exemple, le fichier HTML ne conient aucun élément placé spécifiquement pour effectuer la mise en page. C'est uniquement dans le fichier CSS que la mise en page est effectuée.

Remarque : les couleurs de fond des différentes zones n'ont été ajoutées que pour les rendre plus visibles !

Les quatre grandes parties de la page (<header>, <main>, <aside> et <footer>) ont été définies comme des zones pour la grille (entete, contenu, complements et piedPage). Par défaut, pour les écrans de petite taille, ces quatre zones sont disposées les unes au-dessous des autres grâce à la propriété grid-template-areas.

Lorsque l'écran est un peu plus grand (plus que 576 pixels de large), cette propriété est redéfinie pour obtenir sur une première ligne l'en-tête, sur une seconde ligne le contenu principal, sur le côté le complément, et le pied de page sur une dernière ligne. Afin d'avoir toujours ces éléments-là visibles et d'éviter un ascenseur vertical sur l'ensemble de la page, la propriété height a été définie à 100 vh, c'est-à-dire toute la hauteur de l'écran, et le débordement éventuel de la partie principale a été géré avec la propriété overflow-y à auto.

Pour les écrans encore un peu plus grands (768 pixels de large au minimum), des gouttières sont ajoutées entre les zones et la partie complément est élargie.

Enfin, sur la version pour les grands écrans (largeur minimale de 992 pixels), la largeur des deux colonnes est figée pour que les lignes ne soient pas trop longues et des marges sont positionnées sur les côtés.