Intégration HTML CSS

Les formulaires

Les formulaires sur un site web sont des éléments qui doivent être particulièrement soignés pour favoriser la prise de contact, les conversions,…

Il y a deux aspects à un formulaire. Le premier est ce que vous voyez sur la page elle-même, construit à partir des balises HTML. L’autre composant d’un formulaire est le programme qui va effectuer le traitement des données collectées côté serveur.

L’élément form

L’élément form est un conteneur pour tous les autres éléments des formulaires. Il peut aussi inclure des éléments blocks (h1, p, …).
Vous devez ajouter deux attributs à la balise form :

L’attribut « action »

C’est l’adresse de la page ou du programme qui va traiter les informations. Cette page se chargera de vous envoyer un e-mail avec le message si c’est ce que vous voulez, ou bien d’enregistrer le message avec tous les autres dans une base de données. Cela ne peut pas se faire en HTML ni CSS, on utilisera en général un autre langage dont vous avez peut-être entendu parler : PHP par exemple.

L’attribut « method »

Cet attribut indique par quel moyen les données vont être envoyées au serveur. Il existe deux solutions pour envoyer des données sur le Web :

  • method="get": c’est une méthode en général assez peu adaptée car elle est limitée à 255 caractères. La particularité vient du fait que les informations seront envoyées dans l’adresse de la page
  • method="post": c’est la méthode la plus utilisée pour les formulaires car elle permet d’envoyer un grand nombre d’informations. Les données saisies dans le formulaire ne transitent pas par la barre d’adresse.
<p>Texte avant le formulaire</p>
<form method="post" action="traitement.php">
   <p>Texte à l'intérieur du formulaire</p>
</form>
<p>Texte après le formulaire</p>

Les éléments de saisie

Simple zone de texte

<form method="post" action="traitement.php">
    <input type="text" name="pseudo" placeholder="Ex : Zozor" size="30" maxlength="10" />
</form>
  • L’attribut « type » : définit le type de champ de saisie à utiliser, dans ce cas un champ de saisie de texte simple.
  • L’attribut « name » : est obligatoire, il spécifie le nom de la variable qui va accueillir la valeur saisie par l’internaute dans ce champ.
  • L’attribut « value » : renseigne la valeur par défaut d’un champ.
  • Les attributs « maxlenght » et « minlenght » : indiquent une fourchette de validité de la valeur saisie.
  • L’attribut « size » : définit la longueur du champ, en nombre de caractère.
  • L’attribut « placeholder » : permet de renseigner un texte indicatif par défaut dans un champ de formulaire. C’est une valeur qui s’efface dès que l’utilisateur active le champ de formulaire.

Les libellés

Ils sont utilisés pour associer une étiquette, ou libellé, à un champ de saisie.

<form method="post" action="traitement.php">
    <label for="pseudo">Votre pseudo :</label>
    <input type="text" name="pseudo" id="pseudo" placeholder="Ex : Zozor" size="30" maxlength="10" />
</form>

L’association implicite : c’est quand le champ de saisie est situé à l’intérieur du label.

<form method="post" action="traitement.php">
    <label>
      Votre pseudo :
      <input type="text" name="pseudo" placeholder="Ex : Zozor" size="30" maxlength="10" />
    </label>
</form>

Zone de mot de passe

Comme un champ texte, excepté que les caractères saisis ne s’affichent pas dans le navigateur.

<input type="password" name="motdepasse" maxlength="10" />

Zone de texte multiligne

<textarea name="votre-message" rows="6" cols="64">Le texte par défaut ici...</textarea>

Les zones de saisie enrichies

  • nombre entier (« number »),
  • email (« email »),
  • URL (« url »),
  • date (« date »),
  • mois (« month »),
  • semaine (« week »),
  • date/heure (« datetime »),
  • heure (« time »),
  • plage de valeurs (« range »),
  • téléphone (« tel »),
  • couleur (« color »),

 

Exercice :
Essayez d’utiliser ces différents types de champs de saisie dans différents navigateurs, si possible avec votre smartphone.

Pour tester sur les navigateurs : Page de démonstration des nouveaux champs de formulaire en HTML5.

Pour aller plus loin : Formulaires HTML5 : nouveaux types de champs (Alsacréations)

Les éléments d’options

  • les cases à cocher ;
    <form method="post" action="traitement.php">
       <p>
           Cochez les aliments que vous aimez manger :<br />
           <input type="checkbox" name="frites" id="frites" /> <label for="frites">Frites</label><br />
           <input type="checkbox" name="steak" id="steak" /> <label for="steak">Steak haché</label><br />
           <input type="checkbox" name="epinards" id="epinards" checked="checked" /> <label for="epinards">Epinards</label><br />
           <input type="checkbox" name="huitres" id="huitres" /> <label for="huitres">Huitres</label>
       </p>
    </form>

    Cochez les aliments que vous aimez manger :



  • les zones d’options ;
    <form method="post" action="traitement.php">
       <p>
           Veuillez indiquer la tranche d'âge dans laquelle vous vous situez :<br />
           <input type="radio" name="age" value="moins15" id="moins15" /> <label for="moins15">Moins de 15 ans</label><br />
           <input type="radio" name="age" value="medium15-25" id="medium15-25" checked="checked" /> <label for="medium15-25">15-25 ans</label><br />
           <input type="radio" name="age" value="medium25-40" id="medium25-40" /> <label for="medium25-40">25-40 ans</label><br />
           <input type="radio" name="age" value="plus40" id="plus40" /> <label for="plus40">Encore plus vieux que ça ?!</label>
       </p>
    </form>

    Veuillez indiquer la tranche d’âge dans laquelle vous vous situez :



  • les listes déroulantes.
    <form method="post" action="traitement.php">
       <p>
           <label for="pays">Dans quel pays habitez-vous ?</label><br />
           <select name="pays" id="pays">
               <optgroup label="Europe">
                   <option value="france" selected="selected">France</option>
                   <option value="espagne">Espagne</option>
                   <option value="italie">Italie</option>
                   <option value="royaume-uni">Royaume-Uni</option>
               </optgroup>
               <optgroup label="Amérique">
                   <option value="canada">Canada</option>
                   <option value="etats-unis">Etats-Unis</option>
               </optgroup>
               <optgroup label="Asie">
                   <option value="chine">Chine</option>
                   <option value="japon">Japon</option>
               </optgroup>
           </select>
       </p>
    </form>


Champ de téléversement d’un fichier

Les formulaires peuvent envoyer plus que des données. Ils peuvent être utilisés aussi pour transmettre un document externe, depuis le disque dur de l’utilisateur. Par exemple, une imprimerie peut avoir à demander des créations graphiques pour une commande de cartes de visite.

L’attribut enctype doit alors être stipulé dans l’élément form, et il doit avoir pour valeur multipart/form-data.

<form action ="traitement.php" method="post" enctype="multipart/form-data">
   <label for="photo">Envoyez la photo de profil pour votre avatar</label>
   <input type="file" name="photo" id="photo" />
</form>

Les champs cachés

<input type="hidden" name="reference" value="formulaire contact" />

Regrouper des champs

Si votre formulaire grossit et comporte beaucoup de champs, il peut être utile de les regrouper au sein de plusieurs balises <fieldset>. Chaque <fieldset>peut contenir une légende avec la balise <legend>.

<form method="post" action="traitement.php">
   <fieldset>
       <legend>Vos coordonnées</legend> <!-- Titre du fieldset --> 

       <label for="nom">Quel est votre nom ?</label>
       <input type="text" name="nom" id="nom" />

       <label for="prenom">Quel est votre prénom ?</label>
       <input type="text" name="prenom" id="prenom" />
 
       <label for="email">Quel est votre e-mail ?</label>
       <input type="email" name="email" id="email" />
   </fieldset>
 
   <fieldset>
       <legend>Votre souhait</legend> <!-- Titre du fieldset -->
       <p>
           Faites un souhait que vous voudriez voir exaucé :
           <input type="radio" name="souhait" value="riche" id="riche" /> <label for="riche">Etre riche</label>
           <input type="radio" name="souhait" value="celebre" id="celebre" /> <label for="celebre">Etre célèbre</label>
           <input type="radio" name="souhait" value="intelligent" id="intelligent" /> <label for="intelligent">Etre <strong>encore</strong> plus intelligent</label>
           <input type="radio" name="souhait" value="autre" id="autre" /> <label for="autre">Autre...</label>
       </p>
       <p>
           <label for="precisions">Si "Autre", veuillez préciser :</label>
           <textarea name="precisions" id="precisions" cols="40" rows="4"></textarea>
       </p>
   </fieldset>
</form>

Sélectionner automatiquement un champ

<input type="text" name="prenom" id="prenom" autofocus />

Rendre un champ obligatoire

<input type="text" name="prenom" id="prenom" required />

Le bouton d’envoi

Il ne nous reste plus qu’à créer le bouton d’envoi. Là encore, la balise <input /> vient à notre secours. Elle existe en quatre versions :

  • "submit" : le principal bouton d’envoi de formulaire. C’est celui que vous utiliserez le plus souvent. Le visiteur sera conduit à la page indiquée dans l’attributactiondu formulaire.
  • "reset" : remise à zéro du formulaire.
  • "image" : équivalent du bouton submit, présenté cette fois sous forme d’image. Rajoutez l’attribut src pour indiquer l’URL de l’image.
  • "button" : bouton générique, qui n’aura (par défaut) aucun effet. En général, ce bouton est géré en JavaScript pour exécuter des actions sur la page.
<input type="submit" value="Envoyer" />

 

Exercice

 

  1. Créer l’en-tête HTML, le titre (avec une balise h1) .
  2. Mettre en place le pourtour du formulaire à l’aide de la balise fieldset ; le texte en haut à gauche du cadre s’obtient grâce à la balise legend. La cible du formulaire sera destination.html.
  3. Ajouter les champs noms et prénoms
  4. Ajouter le champ date de naissance (type date)
  5. Ajouter le champ lieu de naissance (type radio) ; les balises nécessaires seront entourées de balises fieldset an d’obtenir l’aspect visuel du cadre. Attention : il faut que le choix soit exclusif, c’est-à-dire qu’on ne puisse pas sélectionner les deux boutons simultanément.
  6. Ajouter le champ adresse postale (balise textarea). La zone de texte fait 2 lignes et 30
    colonnes.
  7. Ajouter le champ code postal (type number)
  8. Ajouter les champs adresse électronique et page personnelle
  9. Ajouter le champ téléphone portable
  10. Ajouter le champ année (balises select). La liste déroulante devra contenir les valeurs B1, B2, B3, M1 et M2.
  11. Ajouter le champ niveau en HTML (type range). La barre devra aller de 0 à 10 avec des pas d’incrément de taille 1.
  12. Ajouter le champ connaissances ; les balises nécessaires seront entourées de balises fieldset afinn d’obtenir l’aspect visuel du cadre.
  13. Ajouter le bouton « Envoyer » (type submit)

 

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8"/>
  <title>Formulaires HTML</title>
</head>
<body>

  <h1>Formulaire élève</h1>

  <form method="post" action="traitement.php">

    <fieldset>
      <legend>Vos données personnelles</legend>

      <p>
        <label for="nom">
          Nom <abbr class="alert" title="Champ obligatoire">*</abbr>: 
        </label>
        <input id="nom" name="nom" type="text" placeholder="Votre nom" required>
      </p>

      <p>
        <label for="prenom">
          Prénom <abbr class="alert" title="Champ obligatoire">*</abbr> : 
        </label>
        <input id="prenom" name="prenom" type="text" placeholder="Votre prénom" required>
      </p>

      <p>
        <label for="date_naissance">
          Date de naissance <abbr class="alert" title="Champ obligatoire">*</abbr> :
        </label>
        <input id="date_naissance" type="date" name="date_naissance" placeholder="JJ/MM/AAAA" required>
      </p>

      <fieldset>
        <legend>Lieu de naissance</legend>

        <p>
          <input id="lieu_naissance_aquitaine" type="radio" name="lieu_naissance">
          <label for="lieu_naissance_aquitaine">
             Nouvelle Aquitaine
          </label>

          <input id="lieu_naissance_ailleurs" type="radio" name="lieu_naissance">
          <label for="lieu_naissance_ailleurs">
             Ailleurs
          </label>
        </p>
      </fieldset>

      <p>
        <label for="adresse">
          Adresse postale :
        </label>
        <textarea id="adresse" cols="30" rows="2"></textarea>
      </p>

      <p>
        <label for="zip">
          Code postal :
        </label>
        <input id="zip" type="number" name="zip">
      </p>

      <p>
        <label for="email">
          Adresse electronique :
        </label>
        <input id="email" type="email" name="email">
      </p>

      <p>
        <label for="url">
          Page personnelle :
        </label>
        <input id="url" type="url" name="url" placeholder="https://www...">
      </p>

      <p>
        <label for="tel">
          Téléphone portable :
        </label>
        <input id="tel" type="tel" name="tel">
      </p>

      <p>
        <label for="semestre">
          Semestre :
        </label>
        <select id="semestre">
          <option>S1</option>
          <option>S2</option>
          <option>S3</option>
          <option>S4</option>
        </select>
      </p>

      <p>
        <label for="html">
          Niveau en HTML :
        </label>
        <input id="html" type="range" value="0" max="10" min="0" step="1">
      </p>

      <fieldset>
        <legend>Connaissances</legend>

        <p>
          <input id="connaissance_html" type="checkbox" name="anniversaire">
          <label for="connaissance_html">
             HTML
          </label>

          <input id="connaissance_css" type="checkbox" name="anniversaire">
          <label for="connaissance_css">
             CSS
          </label>

          <input id="connaissance_formulaires" type="checkbox" name="anniversaire">
          <label for="connaissance_formulaires">
             Formulaires
          </label>

          <input id="connaissance_javascript" type="checkbox" name="anniversaire">
          <label for="connaissance_javascript">
             JavaScript
          </label>
        </p>
      </fieldset>

      <p class="action">
        <input id="" type="submit" value="Envoyer">
       </p>

    </fieldset>
    <p><small><em><abbr class="alert" title="Champ obligatoire">*</abbr> : Obligatoire</em></small></p>
  </form>

</body>
</html>

Mise en page css

Le Flux

Le flux d’un document pourrait se définir comme étant le comportement naturel d’affichage des éléments d’une page web.

L’ordre dans lequel apparaissent les balises dans le code HTML sera l’ordre dans lequel les éléments seront affichés et apparaîtront dans le document, c’est le Flux. Cela signifie que par défaut, chaque élément est dépendant des éléments qui l’entourent.

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.

Structure HTML et rendu CSS des balises : bloc et en-ligne

Historiquement, HTML ne proposait que deux catégories d’éléments : les éléments de niveau block et les éléments de niveau inline. Cette catégorisation autorise ou non certaines imbrications (par exemple un niveau inline de peut pas contenir de niveau block).

  • Les éléments de rendu « bloc » se placent toujours l’un en dessous de l’autre par défaut (comme un retour chariot). Par exemple: une suite de paragraphes (balise p) ou les éléments d’une liste (balise li). Par ailleurs, un élément « bloc » occupe automatiquement, par défaut, toute la largeur disponible dans son conteneur. On peut citer : h1puloldltableblockquoteetc. [liste complète des éléments HTML en bloc]
    • Il occupe l’entièreté de la largeur de son conteneur ;
    • Il permet l’attribution de marges verticales ;
    • Il permet la modification de sa hauteur et largeur.
  • Les éléments de rendu « en-ligne » se placent toujours l’un à côté de l’autre afin de rester dans le texte. Par exemple : le renforcement d’une partie de texte à l’aide de la balise em, ou encore aimgstrongabbr, span, etc. [liste complète des éléments HTML en ligne]
    • Sauf exception, les éléments de type en-ligne n’ont pas de dimension à proprement parler par défaut (il n’occupent que la place minimum nécessaire à leur contenu).

Rendu CSS : la propriété display

Notons que tout élément peut être « reclassé » dans le type opposé grâce à la propriété display. Des propriétés CSS d’un élément (display: blockinlinelist-iteminline-blocktabletable-cell,…) découlent ses spécificités d’affichage, son positionnement dans le flux.

inline-block

Les éléments de rendu inline-block conservent les mêmes caractéristiques que les « inline », mais peuvent être dimensionnés, par exemple la balise <input>.

list-item

Les éléments de rendu list-item ont un rendu de type « block » mais peuvent bénéficier des propriétés CSS liées aux puces (list-stylelist-style-typelist-style-imagelist-style-position , …), par exemple la balise <li>.

table, table-row, table-cell

Les éléments de rendu tabletable-rowtable-cell possèdent le même comportement que les éléments de tableaux et cellules (<table><tr><td>). Ils permettent de centrer les contenus verticalement et d’avoir des hauteurs identiques entre éléments frères, par exemple la balise <td>.

D’autres valeurs pour le display

Voici une liste exhaustive de valeurs pour display

Rendu CSS : La propriété position

La propriété position est celle vers laquelle 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 statique

static est la valeur par défaut de tous les éléments. Un élément avec position: static; n’est positionné d’aucune manière spéciale. Un élément static est dit non positionné et un élément avec une propriété position ayant une valeur autre que static est dit positionné.

La position relative

La position relative (position:relative) permet de décaler un élément par rapport à une position de référence. 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.

Attribuer à un élément une position relative peut ê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 topleft, … 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 fixe

Un élément positionné en fixed est positionné par rapport a la fenêtre du navigateur, ce qui signifie qu’il reste toujours à la même place même si la page défile. De la même manière qu’avec un élément positionné en relative, nous pouvons utiliser les propriétés toprightbottom et left.

Les navigateurs mobiles ont, étonnement, un support très approximatif de la valeur fixed.

La position absolue

absolute est la valeur la plus délicate. absolute se comporte comme fixed sauf que son positionnement est relatif à l’élément parent positionné le plus proche au lieu d’être relatif à la fenêtre du navigateur. Si un élément positionné en absolute n’à aucun élément parent positionné, il utilise le corps du document et se déplace avec le document au défilement de la page. N’oubliez-pas qu’un élément « positionné » est un élément dont la position est tout sauf static.

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 topbottomleft ou right n’a pas été précisée; il s’agit d’ailleurs là d’un comportement applicable à toutes les positions.

La propriété float

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.

Nettoyer les flottants

La propriété clear s’utilise conjointement 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).

 

Exemple

Voici le style de résultat recherché :

Voici notre structure HTML :

<div id="conteneur">
  <div id="header">
    <!-- Ceci est mon haut de page -->
  </div>
  <div class="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>

Avec les positions absolues

#header{background: red;}
#conteneur {width:760px; margin:0 auto;}
#sidebar {background: green;position:absolute; width:170px;}
#contenu {background: blue;margin-left:170px;}
#footer{background: orange;}

Malheureusement, si ma colonne de gauche est plus longue que mon contenu principal, la propriété position ne pourra plus être employée sous peine de voir notre pied de page se superposer en-dessous du header.

Avec des flottements

Nous allons rajouter une division dans notre code HTML afin d’englober l’enfant flottant :

<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 se contentera de sortir du flux l’élément utile :

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

Cependant :

  • 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

Centrage des éléments

Vient toujours le moment où l’on veut centrer des contenus ou tout un site.

Pour centrer horizontalement un texte, on utilisera text-align. Pour centrer horizontalement un bloc, on utilisera la technique des marges automatiques.

#main {
  width: 600px;
  margin: 0 auto; 
}

max-width

Utiliser max-width à la place de width améliorera la gestion des petites fenêtres. C’est très important lorsque l’on créé un site accessible sur mobile.

#main {
  max-width: 600px;
  margin: 0 auto; 
}

Modèles de boîtes et box-sizing

Si nous parlons de la propriété width, nous devrions parler du box model. Quand vous ajustez la propriété width d’un élément, celui-ci peut paraître plus gros que ce que vous avez indiqué : la bordure et le padding de l’élément l’étirent au delà de la largeur spécifiée.
Quand vous ajoutez la propriété box-sizing: border-box; à un élément, le padding et la bordure de cet élément n’augmentent plus sa largeur.

.simple {
  width: 500px;
  margin: 20px auto;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

C’est tellement mieux que certains auteurs veulent que tous les éléments de toutes leurs pages fonctionnent de la même manière. Ils ajoutent donc ce bout de CSS à leurs pages :

* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

Puisque box-sizing est plutôt récent, vous devriez utiliser les préfixes -webkit- et -moz- pour l’instant, comme dans les exemples.

Centrage des éléments absolute

Pour les éléments positionnés en « position: absolute » et autres éléments positionnés hors du flux, la technique des marges latérales automatiques ne fonctionne pas.

Il existe une solution grâce aux transformations et notamment aux translations :

.truc-a-centrer {
  position: absolute; /* postulat de départ */
  top: 50%; left: 50%; /* à 50%/50% du parent référent */
  transform: translate(-50%, -50%); /* décalage de 50% de sa propre taille */
}

Flexbox et Grids

On a tendance à opposer les deux technologies, alors que Flexbox et Grids ont été développés avec des objectifs différents. Ils travaillent même ensemble, ils ne se font pas concurrence.

Concepts de base

Ce sont des méthodes pour créer des structures en grilles, décrites en CSS et non en HTML. Cela nous aide à créer des mises en page qui peuvent être redéfinies à l’aide de Media Queries et s’adapter à différents contextes.

Cela permet de séparer correctement l’ordre des éléments dans la source de leur présentation visuelle. En tant que concepteur, cela signifie que vous êtes libre de modifier l’emplacement des éléments de la page, ce qui peut être utile pour votre mise en page pour votre conception responsive.

Il est très facile de faire en sorte que la grille s’adapte à l’espace disponible. Avec chaque élément ayant une zone sur la grille, les choses ne risquent pas de se chevaucher en raison du changement de taille du texte, de plus de contenu que prévu ou de petites fenêtres.

Cas d’utilisation

Disposition unidimensionnelle

Si vous devez placer votre contenu dans une seule dimension (que ce soit horizontalement ou verticalement), orientez-vous plutôt vers Flexbox.

Disposition bidimensionnelle

Si vous avez besoin d’afficher votre contenu à la fois sur l’axe des x et l’axe des y, cela signifie que vous avez… une grille ! Cette propriété est idéale pour la mise en page non linéaire.

Il y a bien sur des exceptions, mais vous vous sentirez plus à l’aise si vous réservez les Grids pour des dispositions globales complexes et Flexbox pour des mises en page linéaires (ou presque).

Même si leurs objectifs sont différents, ils partagent quelques propriétés communes car ce sont deux outils de mise en page. Les propriétés partagées font partie d’une nouvelle spécification CSS : Box Alignment [https://www.w3.org/TR/css-align-3/], quelque chose que les développeurs attendent depuis très longtemps, vous avez de la chance de na pas avoir connu l’épreuve infernale de l’alignement vertical.

Mise en oeuvre

On crée un « contexte de grille » tout simplement en appliquant la déclaration display: grid à un élément conteneur qui constituera la trame générale, il deviendra un « grid-container » et ses enfants directs des « grid-items ». Cette trame sera définie par un schéma virtuel formé de lignes et colonnes définissant des « cellules ».

Tous les enfants (directs) de ce conteneur général seront automatiquement affectés par ce contexte particulier et pourront se placer au sein des « cellules » de la trame.

Les propriétés usuelles de Grid Layout

Propriété Détails
gridinline-grid déclaration d’un contexte de grille (création d’un « grid-container »)
grid-template-areas déclaration d’un « canevas » de cellules nommées (optionnel)
grid-template-rowsgrid-template-columns déclaration des dimensions de lignes et colonnes
grid-rowgrid-column placement d’un élément « grid-item » dans une ligne ou une colonne
grid-gap, grid-column-gap, grid-row-gap espaces inter-colonnes ou inter-rangées (gouttières)
align-items, justify-items alignement horizontal ou vertical
align-self, justify-self alignement horizontal ou vertical d’éléments distincts

Aligner les éléments à l’intérieur d’un conteneur Flex

Distribuer des éléments à l’intérieur d’un conteneur Flex

Aligner des éléments à l’intérieur d’un conteneur Grid

Arrêtons-nous un instant et jetons un coup d’œil sur cette dernière démo.

Tout d’abord, nous créons une grille à trois colonnes en utilisant la notation repeat(), chaque colonne a une largeur de 1fr;
Ensuite, nous utilisons les propriétés align-items et justify-items pour aligner les cellules dans les axes X et Y et align-self et justify-self pour aligner une cellule spécifique ou l’étirer jusqu’à sa hauteur totale disponible.

Ces propriétés sont partagées par Flexbox, la principale différence est de ne pas utiliser « flex-start » ou « flex-end » mais simplement « start » ou « end« .

Distribuer des éléments à l’intérieur d’un conteneur Grid

Il y a un autre ensemble de propriétés que Flexbox et Grids partageront dans un proche avenir: grid-gap, qui nous permettra de spécifier la distance entre les éléments flex.

Les propriétés grid-row-gap et grid-column-gap seront renommées respectivement row-gap et column-gap.

Flexbox et Grids ensemble

Une fois que vous avez créé votre grille, il est temps d’ajouter le contenu dans les cellules. Que vous souhaitiez ajouter des images, du texte ou les deux, la meilleure façon de les placer au bon endroit est d’utiliser Flexbox.

Prendre en charge le responsive

Contrairement aux float et autres solutions de mise en page, Flexbox et Grids ont été créés à l’ère des multi-appareils. Associé aux CSS3 Media Queries, le modèle de positionnement en grille donne toute sa puissance, plus particulièrement si vous avez opté pour une trame sous forme de variante « template ». En effet, seul le patron de départ nécessite d’être modifié : inutile d’intervenir sur la structure HTML, ni même sur le positionnement de chaque élément de page.

Mise en page responsive avec Flexbox

Flexbox est responsive par défaut. Une fois que vous appliquez display: flex à un élément, vous disposez déjà d’une disposition fluide, mais selon la quantité de contenu que vous avez, vous pouvez appliquer une largeur minimale à vos éléments. Pour ce faire, vous pouvez profiter de flex-base et flex-wrap.

Mise en page responsive avec Grid

Pour être certain que votre disposition en grille sera toujours responsive et que ses composants auront une largeur minimum, nous pouvons utiliser la fonction minmax et la nouvelle unité fr. Cette unité est conçue pour nous aider à créer des grilles flexibles. Un fr est égal à une fraction de l’espace disponible dans le conteneur de la grille. Comme il prend en compte l’écart entre les cellules, il fait tout le calcul pour nous et calcule la bonne largeur pour chaque cellule.

Si vous souhaitez modifier votre mise en page sur de petits écrans, vous pouvez toujours utiliser les media-queries.

Prêts pour la production

Vu la faible compatibilité navigateurs du module Grid Layout actuellement, il est bien entendu utopique d’employer ce type de positionnement en production à l’heure actuelle, même sur des périphériques avant-gardistes.

Si vous souhaitez supporter pleinement tous les navigateurs, vous pouvez utiliser les feature-queries pour fournir une autre disposition pour les navigateurs qui ne supportent pas les Grids ou qui ont une syntaxe plus ancienne.

.grid-parent{
  /* Fallback layout */
}

@supports (display: grid) {
  .grid-parent{
    /* Use grids */
  }
}

Jouons un peu

Pour vous familiariser avec ces deux technologies, je vous propose deux exercices ludiques, que vous pouvez faire directement en ligne :

Ressource utile : Grid by example

 

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8"/>
  <title>Formulaires HTML</title>

  <style>
  body {
    font-family: 'arial', sans-serif;
    background: #f1f1f1;
    font-size: 1em;
    color: #27223A;
  }
  h1 {
    text-align: center;
    margin: 2.5em 0 1em;
    text-transform: uppercase;
    letter-spacing: .05em;
    font-size: 2.4em;
  }
  form {
    width: auto;
    max-width: 60em;
    margin: 2em auto 6em;
    padding: 2em;
    background: #fff;
  }
  @media screen and (min-width: 80em) {
    form {
      width: 50vw;
    }
  }
  fieldset {
    border: 0;
    padding: 2em;
    margin: 0;
  }
  fieldset fieldset {
    padding: .5em 2em 0;
    margin: 2em 0;
    background: #f1f1f1;
    border-radius: 2px;
  }
  legend {
    background: #27223A;
    color: #fff;
    padding: 1em 2em;
    text-transform: uppercase;
    letter-spacing: .25em;
    margin: 0 -5em;
    border-radius: 2px;
  }
  fieldset fieldset legend {
    background: #333;
    padding: .5em 1em;
    letter-spacing: .125em;
    margin: 0 -3em;
    border-radius: 2px;
  }
  p {
    margin: 0 0 1.25em;
    padding: 0;
    width: auto;
    overflow: hidden;
  }
  label {
    display: block;
    line-height: 1.5em;
  }
  @media screen and (min-width: 60em) {
    label {
      float: left;
      width: 40%;
      text-align: right;
      margin-right: 2%;
    }
  }
  fieldset fieldset label {
    float: none;
    width: auto;
    text-align: left;
    margin-right: 3em;
    margin-left: 6px;
    display: inline-block;
  }
  input,
  select {
    font-size: 1em;
    margin: 0;
    line-height: 1.5em;
    border: 0;
    border-bottom: 1px solid #dbdbdb;
    min-width: 250px;
  }
  @media screen and (min-width: 60em) {
    input,
    select {
      max-width: 50%;
    }
  }
  input:focus,
  select:focus {
    border-color: #666;
  }
  input[type="checkbox"],
  input[type="radio"] {
    min-width: 0;
  }
  input[type="range"] {
    position: relative;
    border-bottom: 0;
    margin-left: 1em;
  }
  input[type="range"]:after,
  input[type="range"]:before {
    position: absolute;
    top: 0;
    color: #aaa;
  }
  input[type="range"]:before {
    left:-1em;
    content: attr(min);
  }
  input[type="range"]:after {
    right: -1.5em;
    content: attr(max);
  }
  textarea {
    border: 0;
    width: 95%;
    padding: 0;
    margin: 0;
    line-height: 1.8;
    min-height: 120px;
    background-image: linear-gradient(#dbdbdb 1px, transparent 1px);
    background-color: transparent;
    background-attachment: local;
    background-size: 100% 1.8em;
    margin-top: -2px;
    padding-top: 2px;
    font-size: 1.2em;
    resize: vertical;
  }
  @media screen and (min-width: 60em) {
    textarea {
      width: 58%;
    }
  }
  p.action {
    margin: 4em 0 0;
    text-align: center;
  }
  p.action input[type="submit"] {
    color: #27223A !important;
    background-color: #00FFB4;
    border: 1px solid transparent;
    text-transform: none !important;
    font-size: 1.2em;
    letter-spacing: 0.05em;
    line-height: 22px;
    font-weight: normal;
    border-radius: 50px;
    padding: .75em 2em;
    cursor: pointer;
  }
  p.action input[type="submit"]:hover,
  p.action input[type="submit"]:focus {
    background-color: #fff;
    border-color: #00FFB4;
  }
  :required {
    border-color: #333; 
  }
  .alert {
    color: red;
  }
  abbr.alert {
    text-decoration: none;
  }
  </style>
</head>
<body>

  <h1>Formulaire élève</h1>

  <form method="post" action="traitement.php">

    <fieldset>
      <legend>Vos données personnelles</legend>

      <p>
        <label for="nom">
          Nom <abbr class="alert" title="Champ obligatoire">*</abbr>: 
        </label>
        <input id="nom" name="nom" type="text" placeholder="Votre nom" required>
      </p>

      <p>
        <label for="prenom">
          Prénom <abbr class="alert" title="Champ obligatoire">*</abbr> : 
        </label>
        <input id="prenom" name="prenom" type="text" placeholder="Votre prénom" required>
      </p>

      <p>
        <label for="date_naissance">
          Date de naissance <abbr class="alert" title="Champ obligatoire">*</abbr> :
        </label>
        <input id="date_naissance" type="date" name="date_naissance" placeholder="JJ/MM/AAAA" required>
      </p>

      <fieldset>
        <legend>Lieu de naissance</legend>

        <p>
          <input id="lieu_naissance_aquitaine" type="radio" name="lieu_naissance">
          <label for="lieu_naissance_aquitaine">
             Nouvelle Aquitaine
          </label>

          <input id="lieu_naissance_ailleurs" type="radio" name="lieu_naissance">
          <label for="lieu_naissance_ailleurs">
             Ailleurs
          </label>
        </p>
      </fieldset>

      <p>
        <label for="adresse">
          Adresse postale :
        </label>
        <textarea id="adresse" cols="30" rows="2"></textarea>
      </p>

      <p>
        <label for="zip">
          Code postal :
        </label>
        <input id="zip" type="number" name="zip">
      </p>

      <p>
        <label for="email">
          Adresse electronique :
        </label>
        <input id="email" type="email" name="email">
      </p>

      <p>
        <label for="url">
          Page personnelle :
        </label>
        <input id="url" type="url" name="url" placeholder="https://www...">
      </p>

      <p>
        <label for="tel">
          Téléphone portable :
        </label>
        <input id="tel" type="tel" name="tel">
      </p>

      <p>
        <label for="semestre">
          Semestre :
        </label>
        <select id="semestre">
          <option>S1</option>
          <option>S2</option>
          <option>S3</option>
          <option>S4</option>
        </select>
      </p>

      <p>
        <label for="html">
          Niveau en HTML :
        </label>
        <input id="html" type="range" value="0" max="10" min="0" step="1">
      </p>

      <fieldset>
        <legend>Connaissances</legend>

        <p>
          <input id="connaissance_html" type="checkbox" name="anniversaire">
          <label for="connaissance_html">
             HTML
          </label>

          <input id="connaissance_css" type="checkbox" name="anniversaire">
          <label for="connaissance_css">
             CSS
          </label>

          <input id="connaissance_formulaires" type="checkbox" name="anniversaire">
          <label for="connaissance_formulaires">
             Formulaires
          </label>

          <input id="connaissance_javascript" type="checkbox" name="anniversaire">
          <label for="connaissance_javascript">
             JavaScript
          </label>
        </p>
      </fieldset>

      <p class="action">
        <input id="" type="submit" value="Envoyer">
       </p>

    </fieldset>
    <p><small><em><abbr class="alert" title="Champ obligatoire">*</abbr> : Obligatoire</em></small></p>
  </form>

</body>
</html>