La disposition en CSS

Pour organiser un document en positionnant ses éléments pour que la forme corresponde aux spécifications, on utilisera différentes propriétés CSS afin d'organiser la disposition des élément. CSS fournit de nombreux mécanismes pour organiser la disposition du contenu d'un document et les techniques modernes sont suffisamment complexes pour être décrites dans des articles séparés. Dans cet article, nous verrons les techniques de base, utilisées depuis plusieurs années.

Pour organiser correctement la disposition d'un document avec CSS, il y a quelques notions qu'il est préférable de connaître. Le concept le plus important est le flux du texte HTML et les façons dont on peut le modifier. Ces concepts clés sont essentiels et tous les mécanismes liés à la disposition feront référence à ce qui est expliqué ici..

Le flux

Simplifié à l'extrême, un document HTML est un document texte organisé avec des balises. Dans un tel document, le texte « coule » sur les différentes lignes. Autrement dit, le texte est affiché dans le sens de lecture (de gauche à droite pour les langages latins comme le français ou l'italien) et est fragmenté automatiquement pour passer à la ligne à chaque fois que le texte atteint le bord du document.

Chaque élément du document pourra modifier ce flux de texte :

  • Certains éléments suivront simplement le flux, comme s'ils n'existaient pas
  • Certains éléments pourront forcer le passage à la ligne, que le texte ait atteint la limite du document ou non
  • Certains éléments pourront créer un nouveau flux de texte pour leur contenu, flux indépendant du flux de texte « extérieur ».

Les catégories d'affichage des éléments

CSS est utilisé pour définir la façon dont un élément HTML se comporte dans ce flux et comment il s'y inscrit. Le comportement d'un élément est défini avec la propriété display. Cette propriété peut prendre plusieurs valeurs mais voyons ici les quatre valeurs les plus importantes :

none
Cette valeur retire l'élément du flux, comme si l'élément et son contenu n'existaient pas.
inline
Cette valeur rend l'élément transparent au sens où il s'inscrit dans le flux de texte global, il est donc associé au texte l'environnant.
block
Cette valeur cassera le flux de texte pour insérer l'élément. Cela provoquera donc un saut de ligne avant et après. Le contenu de cet élément ne fait donc pas partie du flux global et suit donc les contraintes de l'élément définies par le modèle de boîte.
inline-block
Cette valeur est en quelque sorte un intermédiaire entre inline et block. Comme avec inline, les boîtes seront placées dans le flux global mais , comme avec block, le contenu ne fera pas partie du texte environnant..

Prenons un exemple.

Voici le code HTML qui sera utilisé :

<p class="none">
  1. Je suis un chat noir,
  <span>qui marche sous l'échelle </span>
  et qui casse des miroirs.
</p>

<p class="inline">
  2. Je suis un chat noir,
  <span>qui marche sous l'échelle </span>
  et qui casse des miroirs.
</p>

<p class="block">
  3. Je suis un chat noir,
  <span>wqui marche sous l'échelle </span>
  et qui casse des miroirs.
</p>

<p class="inline-block">
  4. Je suis un chat noir,
  <span>qui marche sous l'échelle </span>
  et qui casse des miroirs.
</p>

On appliquera la feuille de style CSS suivante :

span {
  width: 5em;
  background: yellow;
}

.none span         { display: none;         }
.inline span       { display: inline;       }
.block span        { display: block;        }
.inline-block span { display: inline-block; }

Cela fournira le résultat suivant :

Modifier le flux

En utilisant la propriété display, vous pouvez déjà modifier le flux. Il est toutefois possible d'aller plus loin.

La disposition du texte

En fin de compte, un document n'est qu'un long flux de texte et CSS fournit de nombreuses propriétés pour gérer la disposition du texte. La disposition du texte regroupe tout ce qui touche aux règles des sauts de ligne et à la façon dont le texte est positionné par rapport à la ligne de base naturelle.

Ces propriétés sont : hyphens, text-align, text-align-last, text-indent, vertical-align, white-space, word-break et word-wrap.

À l'exception de text-align et de text-indent, les autres propriétés ont des effets plutôt subtils sur le texte. Quant à vertical-align, il est souvent utilisé avec des boîtes en mode inline-block.

Là encore, un exemple vaut mieux qu'un long discours.

HTML :

<p lang="en">WHEN Scrooge awoke, it was so dark, that looking out of bed, he could scarcely distinguish the transparent window from the opaque walls of his chamber. He was endeavouring to pierce the darkness with his ferret eyes, when the chimes of a neighbouring church struck the four quarters. So he listened for the hour. To his great astonishment the heavy bell went on from six to seven, and from seven to eight, and regularly up to twelve; then stopped. Twelve! It was past two when he went to bed. The clock was wrong. An icicle must have got into the works. Twelve! He touched the spring of his repeater, to correct this most preposterous clock. Its rapid little pulse beat twelve: and stopped.</p>
<p class="format" lang="en">WHEN Scrooge awoke, it was so dark, that looking out of bed, he could scarcely distinguish the transparent window from the opaque walls of his chamber. He was endeavouring to pierce the darkness with his ferret eyes, when the chimes of a neighbouring church struck the four quarters. So he listened for the hour. To his great astonishment the heavy bell went on from six to seven, and from seven to eight, and regularly up to twelve; then stopped. Twelve! It was past two when he went to bed. The clock was wrong. An icicle must have got into the works. Twelve! He touched the spring of his repeater, to correct this most preposterous clock. Its rapid little pulse beat twelve: and stopped.</p>

CSS :

.format {
  /* On « tire » la première ligne sur
     une distance de 2em */
  text-indent: -2em;

  /* Il faut compenser l'indentation négative
     si on veut éviter que du texte saute et
     pour garder l'ensemble du texte dans la 
     boîte de l'élément */
  padding-left: 2em;

  /* Le texte est aligné par rapport aux deux
     bords et l'espace entre les mots est ajusté
     pour le remplissage de la ligne */
  text-align: justify;

  /* La dernière ligne de texte du bloc est 
     centrée*/
  -moz-text-align-last: center;
       text-align-last: center;

  /* Plutôt que le saut de ligne se fasse entre deux mots,
     il peut être fait en découpant un mot, selon les règles
     de la langue utilisée. Cela permet de découper le texte
     clairement avec un trait d'union. Si cela ne vous
     importe pas, vous pouvez utiliser word-break ou
     word-wrap à la place  */
  -webkit-hyphens: auto;
     -moz-hyphens: auto;
      -ms-hyphens: auto;
          hyphens: auto;
}

Note : Comme vous avez pu le voir, certaines propriétés sont écrites plusieurs fois avec un préfixe. Certaines propriétés sont expérimentales pour certains navigateurs et doivent donc être préfixées, c'est une bonne pratique que de les utiliser préfixées tant qu'elles sont expérimentales, tout en fournissant le nom de la propriété standard à la fin afin d'avoir la meilleure rétrocompatibilité possible.

Le résultat obtenu sera :

Note : L'astuce utilisée pour compenser l'indentation négative est une astuce assez courante. Tout propriété qui accepte une longueur peut accepter une valeur négative. En jouant avec les valeurs négatives et en les compensant avec d'autres propriétés, il est possible de produire des effets visuels très intéressants, notamment quand on manipule les propriétés liées au modèle de boîte.

Le flottement

C'est une chose que de gérer du texte mais on va également vouloir positionner une boîte dans le document. Pour commencer, il faut gérer les boîtes flottantes. Les boîtes flottantes sont toujours attachées au flux global de texte mais le texte « coulera » autour. Si cela vous paraît, prenons un exemple.

Le flottement simple

HTML :

<div>
  <p class="excerpt">"Why, it isn't possible," said Scrooge, "that I can have slept through a whole day and far into another night. It isn't possible that anything has happened to the sun, and this is twelve at noon!" </p>
  <p> The idea being an alarming one, he scrambled out of bed, and groped his way to the window. He was obliged to rub the frost off with the sleeve of his dressing-gown before he could see anything; and could see very little then. All he could make out was, that it was still very foggy and extremely cold, and that there was no noise of people running to and fro, and making a great stir, as there unquestionably would have been if night had beaten off bright day, and taken possession of the world. This was a great relief, because "three days after sight of this First of Exchange pay to Mr. Ebenezer Scrooge or his order," and so forth, would have become a mere United States' security if there were no days to count by.</p>
</div>

CSS :

.excerpt {
  /* Une boîte flottante agira comme un bloc
     quelle que soit la valeur de display */
  display: block;

  /* La boîte flottera à gauche ce qui signifie
     qu'elle sera sur la partie gauche du bloc 
     englobant et que le texte « coulera » sur sa
     droite. */
  float: left;

  /* Il est nécessaire de déclarer une largeur pour
     une boîte flottante. Si on ne le fait pas, la
     largeur sera calculée automatiquement et occupera
     autant d'espace que possible. Cela aurait eu le
     même effet qu'un bloc ordinaire. */
  width: 40%;

  /* On définit une marge à droite et en bas pour éviter
     que le texte qui flotte autour soit collé à celui de
     la boîte */
  margin: 0 1em 1em 0;

  /* On rend la boîte flottante plus visible avec une
     oucleur d'arrière-plan */
  background: lightgrey;

  /* Puisque l'arrière-plan est opaque, on ajoute un écart
     entre le contenu et les bords de la boîte */
  padding: 1em;
}

Ces éléments permettront d'avoir :

Organiser une disposition avec le flottement

La méthode précédente est simple et illustre comment manipuler le flux. Il est possible d'aller plus loin et d'organiser l'ensemble de la disposition du document avec. Les boîtes flottantes dans une direction donnée s'empilent horizontalement, cela permet de créer très facilement des lignes de boîtes. Les boîtes qui sont des blocs forment s'empilent elles sous forme de colonnes.

Là encore, illustrons le point avec un exemple.

HTML :

<div class="layout">
  <div class="row">
    <p class="cell size50">Scrooge went to bed again, and thought, and thought, and thought it over and over and over, and could make nothing of it. The more he thought, the more perplexed he was; and the more he endeavoured not to think, the more he thought.</p>
    <p class="cell size50">Marley's Ghost bothered him exceedingly. Every time he resolved within himself, after mature inquiry, that it was all a dream, his mind flew back again, like a strong spring released, to its first position, and presented the same problem to be worked all through, "Was it a dream or not?"</p>
  </div>
  <div class="row">
    <p class="cell size100">Scrooge lay in this state until the chime had gone three quarters more, when he remembered, on a sudden, that the Ghost had warned him of a visitation when the bell tolled one. He resolved to lie awake until the hour was passed; and, considering that he could no more go to sleep than go to Heaven, this was perhaps the wisest resolution in his power.</p>
  </div>
  <div class="row">
    <p class="cell size33">The quarter was so long, that he was more than once convinced he must have sunk into a doze unconsciously, and missed the clock. At length it broke upon his listening ear.</p>
    <p class="cell size33">
      "Ding, dong!"<br>
      "A quarter past," said Scrooge, counting.<br>
      "Ding, dong!"<br>
      "Half-past!" said Scrooge.<br>
      "Ding, dong!"<br>
      "A quarter to it," said Scrooge.
    </p>
    <p class="cell size33">
      "Ding, dong!"<br>
      "The hour itself," said Scrooge, triumphantly, "and nothing else!"<br>
      He spoke before the hour bell sounded, which it now did with a deep, dull, hollow, melancholy ONE. Light flashed up in the room upon the instant, and the curtains of his bed were drawn.
    </p>
  </div>
</div>

CSS :

/* Le conteneur principal pour la disposition */
.layout {
  /* On ajoute un arrière-plan pour le rendre
     visible */
  background: lightgrey;

  /* On ajoute un léger interstice pour harmoniser
     la distance entre le contenu des cellules et
     la bordure du conteneur principal */
  padding   : 0.5em;
}

/* Ici, on empêche les boîtes flottantes de
   dépasser d'un conteneur (ce qui peut arriver
   si le conteneur est vide car il aura alors
   une hauteur nulle). Avec overflow
   hidden, la boîte flottante ne passera pas à
   travers et la boîte parente sera agrandie
   pour éviter un dépassement de la boîte.  */
.row {
  overflow: hidden;
}

/* Chaque cellule sera une boîte flottante à gauche */
.cell {
  float : left;

  /* On ajoute du padding pour créer un écart visuel
     entre les cellules */
  padding   : 0.5em;

  /* Étant donné qu'on ajoute du padding, il faut
     s'assurer que cela ne touchera pas la largeur
     de la boîte. */
  box-sizing: border-box;

  /* Comme la marge ne peut pas être contrôlée par
     la propriété box-sizing, on s'assure d'en 
     avoir aucune appliquée ici. */
  margin    : 0;
}

/* Voici les tailles appliquées aux boîtes */
.size33  { width:  33%; } /* Pas un tiers mais presque */
.size50  { width:  50%; } /* Une moitié */
.size100 { width: 100%; } /* Une ligne */

Cela donnera le résultat suivant :

De nombreux frameworks CSS utilisent ces méthodes de boîtes flottantes. C'est une technique robuste et connue mais qui a ses limites : tout doit être géré avec le flux, il n'est pas possible de gérer un ordre arbitraire pour les boîtes, de gérer des dimensionnements variables et il est impossible de centrer verticalement des éléments. Nous vous encourageons à poursuivre la réflexion, les boîtes flottantes sont étudiées depuis longtemps (article en anglais) et constituent une des solutions les plus robustes pour gérer une disposition simple, compatible avec les navigateurs historiques.

Si vous souhaitez en savoir plus sur les subtilités des boîtes flottantes, nous vous invitons à lire All about float (en anglais) par Chris Coyer.

Le positionnement

Si les boîtes flottantes font partie du flux, il existe un autre mécanisme qui permet d'organiser une disposition en extrayant les boîtes du flux : le positionnement CSS. Le positionnement fonctionne en définissant un contexte de positionnement grâce à la propriété position puis en permettant aux boites de se positionner en utilisant les propriétés top, left, right, and bottom.

La propriété position peut prendre quatre valeurs différentes :

static
La valeur par défaut pour tous les éléments : ils font partie du flux et on ne définit pas un contexte de positionnement spécifique.
relative
Avec cette valeur, les éléments font toujours partie du flux mais peuvent être déplacés visuellement avec les valeurs des propriétés top, left, right et bottom. Ces propriétés définissent le contexte de positionnement des éléments fils.
absolute
Avec cette valeur, les éléments ne sont plus placés dans le flux et ne l'influencent plus. La position du bloc est définie avec les propriétés top, left, right et bottom. Le point de position 0,0  représente le coin en haut à gauche de l'élément parent le plus proche qui définit un contexte de positionnement autre que static. S'il n'y a pas de tel parent, la position 0,0 représente le coin en haut à gauche du document.
fixed
Avec cette valeur, les éléments ne sont plus placés dans le flux et ne l'influencent plus. La position du bloc est définie avec les propriétés top, left, right, and bottom. La position 0,0 représente le coin en haut à gauche de fenêtre du navigateur (viewport).

Les boîtes positionnées de cette façon peuvent s'empiler les unes sur les autres. Dans ce cas, il est possible de changer l'ordre d'empilement grâce à la propriété z-index.

Une dernière fois, prenons un exemple pour illustrer le concept.

Le code HTML pour le document sera :

<p>
  The curtains of his bed were drawn aside, I tell you, by a hand. Not the curtains at his feet, nor the curtains at his back, but those to which his face was addressed. The curtains of his bed were drawn aside; and Scrooge, starting up into a half-recumbent attitude, found himself face to face with the unearthly visitor who drew them: as close to it as I am now to you, and I am standing in the spirit at your elbow.
  <span class="topleft">1</span>
</p>
<p class="relative">
  It was a strange figure--like a child: yet not so like a child as like an old man, viewed through some supernatural medium, which gave him the appearance of having receded from the view, and being diminished to a child's proportion. Its hair, which hung about its neck and down its back, was white as if with age; and yet the face had not a wrinkle in it, and the tenderest bloom was on the skin. The arms were very long and muscular; the hands the same, as if its hold were of uncommon strength. Its legs and feet, most delicately formed, were, like those upper members, bare. It wore a tunic of the purest white; and round its waist was bound a lustrous belt, the sheen of which was beautiful. It held a branch of fresh green holly in its hand; and, in singular contradiction of that wintry emblem, had its dress trimmed with summer flowers. But the strangest thing about it was, that from the crown of its head there sprung a bright clear jet of light, by which all this was visible; and which was doubtless the occasion of its using, in its duller moments, a great extinguisher for a cap, which it now held under its arm.
  <span class="topleft">2</span>
  <span class="stackdown">3</span>
  <span class="stackup">4</span>
</p>

La feuille de style CSS sera :

p {
  margin: 1em
}

span {
  font       : 2em sans-serif;
  width      : 6rem;

  /* Avoir la hauteur de l'élément et la hauteur
     de la ligne avec la même valeur permet de 
     centrer verticalement une ligne de texte. */
  height     : 6rem;
  line-height: 6rem;

  text-align : center;
  background : rgba(0, 255, 255, 0.8);
}

.relative {
  position: relative;
}

/* Tous les éléments de la classe "topleft"
   sont positionnés dans le coin en haut à 
   gauche de leur parent dans le contexte 
   de positionnement */
.topleft {
  position: absolute;
  top     : 0;
  left    : 0;
}

.stackup {
  position: absolute;
  top     : 37%;
  left    : 62%;

  /* Tous les éléments de la classe "stackup"
     sont placés au-dessus des éléments dont
     le z-index est inférieur à 2 dans le même
     contexte de positionnement. */
  z-index : 2;
}

.stackdown {
  position: absolute;
  top     : 50%;
  left    : 66%;

  /* Tous les éléments de la classe "stackdown"
     sont placés sous les éléments dont le 
     z-index est supérieur à 1 dans le même
     contexte de positionnement. */
  z-index : 1;
}

La combinaison de ces deux éléments donnera le résultat suivant :

Bien que le positionnement CSS ne soit pas réellement utile pour complètement organiser une disposition, il est généralement judicieux pour obtenir certains effets liés à la navigation, aux bulles d'informations, etc. C'est un mécanisme que vous rencontrerez fréquemment et nous vous encourageons donc à vous familiariser avec. Parmi les ressources qui existent par ailleurs, nous vous conseillons particulièrement de lire l'article CSS positioning 101 (en anglais), de Noah Stokes.

La suite

Le flux, les boîtes flottantes et le positionnement CSS sont les bases qui vous permettront d'approfondir la création d'une disposition en CSS. Suite à cette série d'articles sur les concepts théoriques de CSS, vous connaissez tout ce qu'il faut pour exploiter au mieux CSS. Après ce vernis théorique, vous pouvez aborder les aspects pratiques de CSS. Si vous souhaitez approfondir les concepts sur la disposition et découvrir les autres mécanismes à ce sujet, vous pouvez consulter les articles sur : les tableaux, l'organisation à plusieurs colonnes et la disposition avec les boîtes flexibles (flexbox).

Étiquettes et contributeurs liés au document

Étiquettes : 
 Contributeurs à cette page : SphinxKnight
 Dernière mise à jour par : SphinxKnight,