Leçon 12 : Mise en page à l’ancienne

Leçon Progress:

Objectifs

  1. réaliser une mise en page en modifiant le placement par défaut en HTML
  2. connaître le principe de techniques « anciennes » vouées à être remplacée par Flexbox

La mise en page pose deux questions essentielles :

  1. Comment placer ou disposer les blocs les uns par rapport aux autres ?
  2. Comment doivent se comporter les blocs, pour leur taille et leur placement, lorsque la fenêtre change de taille ?

Dans cette leçon, nous traitons uniquement de la première question, avec des techniques qui ont vocationà être remplacée par Flexbox. La deuxième question est plus générale et relève du type de maquette choisie, adaptée ou non à différente taille d’écran. Elle fait l’objet du dernier chapitre.

La précédente leçon est essentielle pour comprendre et maîtriser les techniques que nous allons voir pour la mise en page. Le but est de choisir la disposition des blocs dans une page pour correspondre à une maquette, fil-de-fer ou graphique.

Rappelons brièvement ces principes, avec deux comportements :

  1. en ligne : les éléments se placent sur la même ligne vers la droite puis vers le bas quand le bord de la fenêtre est atteint ; leurs dimensions épousent simplement leur contenu textuel ou images
  2. bloc : les éléments se superposent et occupent toute la largeur, leur hauteur dépendant évidemment de la disposition et des dimensions de leur contenu

Ces principes peuvent convenir lorsque les blocs, qui utilisent pleinement le modèle de boîte avec une couleur de fond, une marge, une bordure, occupent toute la largeur. Nous allons voir différentes techniques qui changent ce comportement sur trois points précis essentiels :

  1. changer la largeur d’un élément avec le style display :
    • soit fixe, ce qui est impossible pour un élément en ligne
    • soit adaptée au contenu et non pas à 100% comme le font les éléments de type bloc
  2. mettre deux blocs côte-à-côte avec le style float
  3. changer le placement d’un élément par rapport à son conteneur, centré ou aligné à droite par exemple, à l’aide de différentes techniques dont le style position

Propriété CSS display

La propriété CSS : display prend deux valeurs de base pour les deux comportements type : inline (en ligne) ou block (bloc). En vérité, display, possède un grand nombre de valeurs, qui augmente régulièrement, nous verrons les principales au fur à et mesure.

Transformer en bloc un élément en ligne

Le cas peut se produire par exemple avec une suite de liens ou une suite d’images que l’on veut superposer. Voici un exemple avec trois images qui s’affichent normalement sur la même ligne. Un petit display:block change simplement cela. Vous noterez que le fait d’insérer dans le code un espace ou un retour à la ligne entre deux images fait qu’il y a un petit espace entre elle dans le rendu visuel (il faut enlever bien sûr la propriété display pour les remettre en ligne).

<!DOCTYPE html>
<html lang="fr">
<head>
   <title>Images superposées</title>
   <meta charset="utf-8">
   <style>
      .liste-img img {
         display: block;
         border: 1px solid black;
      }   
   </style>
</head>

<body>
   <div class="liste-img">
      <img src="" width="100" height="100" />
      <img src="" width="100" height="100" />
      <img src="" width="100" height="100" />
   </div>
</body>
</html>
technique display:block
principe Transforme en élément de type bloc
cas d’utilisation
  • superposer des éléments par nature en ligne
  • appliquer le modèle de boîte (marges, bordures, largeur) à un élément en ligne
  • retirer l’espace à droite d’un élément en ligne, une image par exemple

Transformer en ligne un élément bloc

Facile, en écrivant display:inline, mais peu utile car on perd tout le modèle boîte comme nous l’avons vu.

 

Vérifiez-le avec cet exemple très parlant. Les trois liens sont placés dans une liste, comme cela est la tradition pour donner du sens à ce groupement de liens. Les éléments li sont des blocs, donc les liens se superposent. Si nous voulons les aligner, l’idée est de passer en display:inline les li.

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Ma page</title>
      <meta charset="utf-8">
      <style>
         .menu {
            background-color: aliceblue;
         }
         .menu li {
            display: inline;
            border: 1px solid black;
            padding: 3px 10px;
            margin: 4px;
         }
         .menu a {
            text-decoration: none;
            color: red;
         }
      </style>
   </head>
   <body>
      <ul class="menu">
         <li><a href="">Lien 1</a></li>
         <li><a href="">Lien 2</a></li>
         <li><a href="">Lien 3</a></li>
      </ul>
   </body>
</html>

Tout va bien jusqu’à ce qu’on décide de colorer le fond de la barre de menu représentée par l’élément ul. Mauvaise surprise, la boîte des liens débordent car le modèle de boîte ne s’applique pas complètement.

Il faudrait pouvoir garder le modèle de boîte des blocs tout en les alignant, faire du bloc en ligne ou du en ligne bloc.

C’est possible grâce à une valeur qui justement combine les deux : inline-block !

Bloc à l’intérieur, en ligne à l’extérieur

La directive CSS à utiliser est display:inline-block, à placer sur chacun des éléments à aligner (comportement « extérieur ») tout en gardant le modèle de boîte (comportement « intérieur »).

Dans l’exemple précédent, remplacez display:inline par display:inline-block dans la déclaration de .menu li et vous verrez que l’aspect s’améliore.

Il reste un petit soucis, dans le cas où vous ne voulez absolument pas d’espace entre les éléments en inline-block. C’est un problème connu et largement documenté sur Internet, voyez cette article sur css-tricks. Cet espace visuel est dû aux espaces ou retour à la ligne dans le code HTML, inévitable si l’on veut indenter le code. Il n’y a pas de solution élégante à moins d’utiliser Flexbox que nous verrons à la prochaine leçon, ou éventuellement la propriété float, décrite plus bas, mais qui peut poser plus problèmes qu’elle n’en règle. En gardant inline-block, je vous propose deux solutions :

  1. mettre dans le code tous les li sur la même ligne, collés (pas terrible !)
  2. insérer un faux commentaire qui « absorbe » tous les espaces de l’indentation (un peu mieux mais pas top)

La deuxième solution est mise en œuvre dans le code suivant, à tester.

code
<!DOCTYPE html>
<html lang="fr">
   <head>float
      <title>Ma page</title>
      <meta charset="utf-8">
      <style>
         .menu {
            background-color: aliceblue;
         }
         .menu li {
            display: inline-block;
            border: 2px solid black;
            border-right-style: hidden;
            padding: 5px 10px;
            margin: 4px 0;
         }
         .menu li:last-child {
            border-right-style: solid;
         }
         .menu a {
            text-decoration: none;
            color: red;
         }
      </style>
   </head>

   <body>
      <ul class="menu">
         <li><a href="#">Lien 1</a></li><!--
         --><li><a href="#">Lien 2</a></li><!--
         --><li><a href="#">Lien 3</a></li>
      </ul>
   </body>
</html>
rendu visuel

Cette technique présente d’autres intérêts, décrits dans ce résumé.

technique display:inline-block
principe Transforme en élément se comportant comme un bloc à l’intérieur mais placé comme un élément en ligne
cas d’utilisation
  • mettre sur la même ligne des blocs avec un fond ou une bordure tout en les laissant dans leur conteneur (immense avantage sur l’infâme float)
  • appliquer le modèle de boîte (marges, bordures, largeur) à un élément en ligne tout en le laissant placé en ligne
  • faire qu’un élément soit dimensionné par rapport à son contenu

Exercice 1

A partir d’un code HTML unique, vous devez réaliser le menu montré dans les vidéos, avec deux mises en formes différentes. Chaque mise en forma aura une feuille de style propre qui s’appliquera à la même page. Voici les consignes :

  1. Utiliser display:inline-block pour aligner les éléments de menu, dans une structure ul/li/a
  2. Le lien doit être cliquable sur toute la surface d’un élément de menu, jusqu’au bord, ce que ne permet pas le comportement par défaut de la balise <a> (à vous de trouver la solution en CSS)
  3. Au survol d’un élément, pour la mise en forme A, la couleur de fond change et la bordure disparaît, pour la B un souligné fait par une bordure apparaît ; dans les deux cas, il faut éviter un déplacement des objets ou des bords, il faut donc trouver une technique qui compense l’ajout ou la disparition d’un bord (marge à la place d’un bord, bord transparent, etc)
  4. Les dimensions dans les deux cas sont les mêmes : police à 125%, marge intérieure à déterminer (ici 15px horizontal, 6px vertical)
  5. le bloc de menu est centré (il faut donc un conteneur, header par exemple, et utiliser align-center) et sa bordure occupe l’espace du menu et non toute la largeur, ce qui oblige à changer la propriété display

TypeNomTaille

mkv
Exo1 Demo Menua 353.6k

mkv
Exo1 Demo Menub 425.7k

Les objets flottants

Attention, nous entrons en terrain miné, avec une propriété CSS destinée à l’habillage du texte, en combinant des images et du texte par exemple dans un article, qui a été largement dévoyée pour faire de la mise en page. Il s’agit de la propriété float quo prendre comme valeur left ou right pour simplement demander à un objet, souvent une image, de se placer à gauche ou à droite d’un contenu textuel qui épouse ses formes. Un exemple est plus parlant :

<!DOCTYPE html>
<html lang="fr">
<head>
   <title>Ma page</title>
   <meta charset="utf-8">
   <style>
      article {
         width: 400px;
      }
      img {
         float: left;
      }
   </style>
</head>

<body>
   <article>
      <img src="lorem.svg" width="100" />
      <p>
         Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore hic libero quam molestias obcaecati, minus deleniti eaque! Tenetur dolor sequi, facilis dolorem itaque rerum beatae velit, repellat id cupiditate cum.
         Ea corporis accusantium deleniti nam architecto commodi eum aperiam ratione accusamus. Iste dolorem unde laboriosam voluptatem corrupti totam obcaecati impedit aliquam nisi cum, accusantium, molestiae ullam. Inventore non maxime provident!
      </p>
      <p>
         Excepturi aliquid maiores soluta nobis et nostrum dolores officia, tempore. Quae nulla ea laborum quam illo architecto assumenda, natus cumque eligendi eum accusantium delectus ut alias, cupiditate adipisci non sint!
         Molestias quam pariatur natus. Quasi, deserunt laudantium ipsam nam esse, quisquam, pariatur odit praesentium asperiores error ea repellendus? Quibusdam nihil consectetur fuga amet sunt architecto velit illum reiciendis labore tempore.
      </p>
   </article>
</body>
</html>

Exécutez ce code HTML pour voir le résultat, avec et sans la directive CSS float:left,en utilisant cette image :

Mise en page avec float

Peu de temps après l’introduction de cette propriété, l’idée a germé dans l’esprit des intégrateurs pour aligner des éléments comme le fait inline-block (c’était avant que celle-ci soit introduite). Pour cela, et pour éviter toutes les déconvenues et problèmes que provoque cet usage, il faut bien comprendre comment fonction float.

L’élément qui reçoit cette propriété :

  1. sort du flux HTML et devient « flottant »
  2. se place sur la « même ligne », à droite ou à gauche, c’est-à-dire se place horizontalement sans bouger verticalement
  3. le contenu à cet emplacement est alors poussé pour que l’objet s’affiche correctement sans superposition ; le texte de ce contenu se déroule autour de l’élément flottant

La « sortie du flux » est importante, c’est comme si l’objet flottant n’avait jamais été inséré dans son parent qui donc n’est plus contraint par celui-ci.

Appliquons cette idée à l’exemple précédent avec « lien1 lien 2 lien 3 », en utilisant float:left à la place de display:inline-block. Nous avons ajouté un paragraphe pour représenter un contenu à afficher sous le menu.

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Ma page</title>
      <meta charset="utf-8">
      <style>
         .menu {
            background-color: #adc4d8;
            
            /* on enlève la puce */
            list-style-type: none;
         }
         .menu li {
            float: left; /* les li sont flottants à gauche */
            border: 2px solid black;
            border-right-style: hidden;
            padding: 5px 10px;
            margin: 4px 0;
         }
         .menu li:last-child {
            border-right-style: solid;
         }
         .menu a {
            text-decoration: none;
            color: red;
         }
      </style>
   </head>

   <body>
      <ul class="menu">
         <li><a href="#">Lien 1</a></li><!--
         --><li><a href="#">Lien 2</a></li><!--
         --><li><a href="#">Lien 3</a></li>
      </ul>
      <p>Le contenu</p>
   </body>
</html>

Les puces qui disparaissaient grâce à inline-block reviennent, ça n’est pas un souci grâce à list-style-type. Mais deux problèmes majeurs surviennent conséquence directe du fonctionnement de float :

  1. le fond bleu du menu disparaît car l’élément <ul> ne contient plus les <li> qui sortent du flux et donc est vide
  2. le « contenu » se colle à droite du menu, normal car les trois <li> flottants se placent à gauche du contenu qui suit

Le deuxième problème a été réglé en introduisant une propriété spécialement pour cela, et là on touche au côté hautement bidouillesque de float. Il s’agit de clear à placer sur un élément qui ne doit pas avoir de flottants à sa gauche (valeur left), à sa droite (valeur right) ou partout (valeur both). Donc ici, on applique cette propriété au <p> pour le forcer à se placer en dessous :

p {
   clear: both;
}

Avec le premier problème, on touche au cœur des soucis qu’apporte l’usage de float pour la mise en page. Le conteneur étant vide car les éléments du menu sortent du flux, sa hauteur est nulle. Une solution basique consiste à fixer la hauteur du conteneur, ici par exemple height:40px sur le <ul> qui a la couleur de fond. C’est pas terrible car on perd la dimension automatique du conteneur, pratique en toute circonstance, par exemple si on réduit la largeur de fenêtre (ou si on zoome) et que notre menu s’affiche sur deux lignes. Dans ce cas, la hauteur à 40 pixels ne convient pas. Tout ces inconvénients disparaissent avec inline-block et surtout avec Flexbox que nous verrons au chapitre suivant.

Dernier petit soucis avec float pour la mise en page. Reprenons l’exemple précédent de l’image à gauche d’un paragraphe. Si l’on souhaite une composition où le paragraphe est à droite, avec son texte aligné et non pas entourant l’image, il faut employer overflow:auto sur le paragraphe. Voici ce que cela donne sur l’exemple précédent :

<!DOCTYPE html>
<html lang="fr">
<head>
   <title>Ma page</title>
   <meta charset="utf-8">
   <style>
      article {
         width: 400px;
      }
      img {
         float: left;
      }
      p {
         overflow: auto;
      }
   </style>
</head>

<body>
   <article>
      <img src="lorem.svg" width="100" />
      <p>
         Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore hic libero quam molestias obcaecati, minus deleniti eaque! Tenetur dolor sequi, facilis dolorem itaque rerum beatae velit, repellat id cupiditate cum.
         Ea corporis accusantium deleniti nam architecto commodi eum aperiam ratione accusamus. Iste dolorem unde laboriosam voluptatem corrupti totam obcaecati impedit aliquam nisi cum, accusantium, molestiae ullam. Inventore non maxime provident!
      </p>
   </article>
</body>
</html>

On obtient le résultat souhaité :

Centrage

Le centrage a toujours posé des problèmes en HTML/CSS, parfois parce qu’il était mal compris. Nous abordons ici les techniques en usage avant Flexbox. Certains relèvent de l’astuce et sont désormais avantageusement remplacée par Flexbox.

Centrage horizontal

Éléments en ligne

Ici, point de mystère, nous avons déjà amplement utilisé text-align:center, qui reste d’actualité, Flexbox étant plutôt utilisé pour des blocs. Tous le contenu en ligne dans un bloc qui reçoit text-align:center (valable aussi avec right et left) se centre horizontalement dans ce bloc. Prenez garde que ce style est hérité, il s’applique à tout le texte (contenu en ligne) même dans les sous-éléments.

Testez ce style avec le code qui suit. Essayez d’abord d’imaginer le résultat puis essayez-le dans un navigateur web.

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Ma page</title>
      <meta charset="utf-8">
   </head>
   <style>
      .header {
         text-align: center;
         border: 2px solid red;
      }
      .header a {
         display: inline-block; /* pour avoir les marges haute et basse */
         margin: 5px;
      }
      h1 {
         margin-left: 25%;
         margin-right: 5px;
         border: 2px solid green;
      }
   </style>
   <body>
      <header class="header">
         <a href="#">Option  1</a><a href="#">Option 2</a>
         <h1><img src="lorem.svg" width="60" alt="logo">Titre</h1>
      </header>
   </body>
</html>

Éléments blocs

Une marge « automatique » à droite et à gauche (margin-left:auto, margin-right:auto) permet de centrer un bloc dans un bloc plus grand à condition que le bloc intérieur ait une largeur fixée, soit dans le code HTML (une image par exemple avec l’attribut width que l’on bascule en bloc), soit par le style width.

En voici un exemple commenté :

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Centrage horizontal de bloc</title>
      <meta charset="utf-8">
   </head>
   <style>
      .header {
         border: 2px solid red;
      }
      h1 {
         margin-left: auto;
         margin-right: auto;
         width: 50%;
         border: 2px solid green;
      }
      h1 img {
         margin: auto;
         display: block;
      }
   </style>
   <body>
      <header class="header">
         <h1><img src="lorem.svg" width="60" alt="logo">Titre</h1>
      </header>
   </body>
</html>
  1. le bloc h1 a une taille fixé à 50 % de celle de son conteneur, la marge automatique peut s’appliquer
  2. le bloc h1 est centré grâce aux deux marges auto, à noter que l’on peut écrire margin:10px auto pour fixer les marges haut et bas, ou simplement margin:auto si celles-ci n’ont pas d’importance et doivent être nulle
  3. l’image dans le h1 est transformée en bloc de façon à la placer au-dessus du texte et à pouvoir la centrer par margin:auto
A noter qu’en employant que margin-right:auto ou margin-left:auto, on cale à gauche ou à droite un bloc.

Voici une situation où la marge automatique sur la section n’a aucun effet car même si son contenu est réduit, sa largeur est maximale et occupe tout son conteneur en l’absence de style width :

<!DOCTYPE html>
<html lang="fr">
   <head>
      <title>Centrage horizontal de bloc</title>
      <meta charset="utf-8">
   </head>
   <style>
      main {
         border: 2px solid red;
      }
      section {
         border: 2px solid green;
         margin: auto;
      }
      p {
         width: 150px;
      }
   </style>
   <body>
      <main>
         <section>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates porro illum deserunt temporibus est eaque reprehenderit, nesciunt amet laborum hic, ea aut eveniet iste aliquid, quaerat ab quibusdam ratione ut.</p>
         </section>
      </main>
   </body>
</html>

Au passage, à titre d’exercice, trouvez une solution pour centrer horizontalement la section dans son conteneur sans en fixer la largeur. Le but est que sa largeur s’adapte à son contenu et que le centrage soit possible. Vous devez réaliser cela avec la propriété display vue plus haut, snas utiliser bien sûr Flexbow que nous n’avons pas encore traité.

Centrage vertical

Nous entrons en terrain glissant, ce besoin ayant toujours posé problème en HTML/CSS.

Elements en ligne

Nous avons déjà traité ce cas au chapitre III avec vertical-align:middle. Ce centrage est limité car :

  1. il agit sur une succession d’éléments en ligne (texte, liens, image) en alignant par rapport à la ligne de base des caractères
  2. il n’agit pas par rapport au conteneur alors que c’est souvent le centrage vertical que l’on souhaite

Pour ces motifs, il est peu utilisé sauf dans un tableau ou il agit pleinement dans une cellule.

Qu’avions-nous à disposition avant l’introduction de Flexbocx ? Uniquement des astuces plus ou moins efficaces.

Première astuce : la hauteur de ligne

La procédure est la suivante, ces étapes montrant bien que cette technqiue est d’un usage délicat :

  1. le conteneur, dans lequel le centrage vertical s’applique, à une hauteur fixé par height
  2. l’interligne est fixé par line-height, à la même valeur
  3. cela ne fonctionne que pour l’affichage du texte sur une seule ligne, sinon l’interligne s’applique et la deuxième ligne est éloignée !

Un exemple simple :

<!DOCTYPE html>
<html lang="fr">
<head>
   <title>Ma page</title>
   <meta charset="utf-8">
   <style>
      h1 {
         background-color: cadetblue;
         height: 150px;
         line-height: 150px;
         font-size: 60px;
         white-space: nowrap;
         overflow: hidden;
      }
   </style>
</head>

<body>
   <h1>Titre sur une seul ligne</h1>
</body>
</html>

Testez ce code et regardez ce qu’il se passe en enlevant white-space qui empêche la coupure du titre sur deux lignes (overflow évite tout débordement).

Éléments blocs

Voyons la deuxième astuce qui s’applique dans ce cas :

<!DOCTYPE html>
<html lang="fr">
<head>
   <title>Ma page</title>
   <meta charset="utf-8">
   <style>
      main {
         height: 300px;
         border: 2px solid red;
         position: relative;
      }
      article {
         position: absolute;
         top: 50%;
         transform: translateY(-50%);
         border: 2px solid green;
      }
   </style>
</head>

<body>
   <main>
      <article>
         <img src="lorem.svg">
         Légende de l'image
      </article>
   </main>
</body>
</html>

Testez-le. Vous verrez que le bloc de bord vert (article) est centrée verticalement par rapport à son conteneur de bord rouge (main). Ok, vous n’y comprenez rien, c’est normal. Ce sera (un peu) plus clair quand nous aurons vu le style position. L’idée générale est que le bloc est descendu au niveau du milieu de son parent (top: 50%) et ensuite remonté de la moitié de sa hauteur (transform et là, particularité de tranform, les pourcentages sont relatif au bloc lui-même et pas à son parent). Oui, ça va loin et heureusement Flexbox va nous libérer de ces astuces qui restent limitées.

Bien sûr, si l’on travaille en maquette fixe en pixel, il est possible de fixer la hauteur des blocs et de jouer à l’intérieur sur les marges pour centrer. Très mauvaise technique dont encore une fois Flexbox va nous libérer.

Exercice 2

A partir du code HTML fourni, vous devez appliquer des styles pour obtenir la mise en page montrée dans le PDF en utilisant exclusivement float pour le placement des blocs. En particulier, il faut réaliser les opérations suivantes :

  1. Il est impératif de ne pas toucher au code HML, l’ordre des images d’entête est voulu pour permettre l’utilisation de float
  2. Les images ont une marge de 10 pixels autour d’elle, ce qui donne 150 pixels pour la hauteur de l’entête (malheuresement height sur le bandeau est obligatoire car nous sortons les images du flux)
  3. Dans l’entête placer une image à droite et une à gauche du bandeau en utilisant float
  4. Centrer horizontalement le titre dans le bandeau d’entête
  5. Les sections sont affichées sous la forme de trois colonnes extensibles (utiliser width: 33.33%) à placer ainsi toujours avec float
  6. Dans la colonne 3, une petite image vient illustrer le texte qui l’entoure
TypeNomTaille

html
Header Col 2.1k

pdf
Header Col 63.6k

svg
Lorem 53.2k

Pour le centrage vertical du titre, essayez différentes techniques pour en comprendre le fonctionnement :

  1. grosse triche en mettant une marge haute appropriée, à partir de la hauteur du bandeau et de la hauteur de l’image
  2. technique line-height avec l’inconvénient que si l’on réduit la largeur de la fenêtre, ça peut devenir très moche !
  3. technique la plus fiable mais lourde à écrire avec translate(50%)
A retenir

 

Ressources utiles
Téléchargements
TypeNomTaille

mkv
Exo1 Demo Menua 353.6k

mkv
Exo1 Demo Menub 425.7k

html
Header Col 2.1k

pdf
Header Col 63.6k

svg
Lorem 53.2k
Télécharger

Pour aller plus loin

Laisser un commentaire