Le jeux de float, clear et clearfix en HTML/CSS
2018-04-05

Le menu horizontal sous la barre de titre de mes pages est constitué de deux blocs <div> flottants. À gauche, il n'y a qu'un seul lien Accueil, à droite le bloc contient les autres liens À propos, Programmation et ainsi de suite. L'alignement vertical de l'élément suivant (une boîte de recherche, une date, ou un paragraphe, selon le cas) était délicat et ma solution était des pires possibles. Il était temps de revoir cette question. Encore une fois, plusieurs ont déjà trouvé de bonnes solutions.

Table des matières

  1. L'énoncé du problème
  2. La solution <br... de W3C
  3. La solution clearfix
  4. Tout était prévu : overflow
  5. Le nouveau clearfix moderne
  6. Conclusion

  1. L'énoncé du problème
  2. Voici une situation problématique que l'on rencontre souvent. En premier, il y a un bloc conteneur de type <div> qui occupera 90% de la largeur totale et qui sera centrée. Entre les balises définissant ce conteneur il y a un paragraphe affichant une date alignée au centre et deux autres zones <div> contenant du texte, l'une qui flotte à gauche et l'autre à droite. Enfin, la zone conteneur est suivie d'un paragraphe affichant une seconde date alignée sur la marge droite.

    <div style="width:90%; border:1px solid green; margin-left:auto; margin-right:auto"> <p style="text-align:center">date: 2018-02-03</p> <div style="float: left; width:40%; border:1px solid red"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse. </div> <div style="float: right; width:40%; border:1px solid blue"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam. </div> </div> <p style="text-align:right; border:1px solid #aaa; margin:0; padding:0">date: 2018-02-04</p>

    Où sera situé la seconde date ? Probablement pas où l'on voudrait comme on peut voir ci-dessous.



    date: 2018-02-03

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam.

    date: 2018-02-04




    Parce qu'elles sont des zones flottants, les deux zones de texte ne sont pas contenues graphiquement dans la zone conteneur même si elles sont comprises entre les balises <div> et </div> de la zone conteneur. Le contour vert montre que la taille verticale de la zone conteneur ne tient compte que de la première date. Donc le fureteur place la seconde date sous cette zone, mais sans que son texte empiète sur les zones flottantes. Par contre, le cadre autour du paragraphe qui occupe toute la largeur de son contenant est par dessus les zones flottantes.

    J'essayais de régler le problème en fixant la taille verticale de la zone conteneur. Cette méthode est franchement mauvaise. Il suffit de réduire la taille horizontale de la fenêtre du fureteur pour que les deux zones de texte flottantes occupent un espace vertical croissant qui pouvait éventuellement dépasser la taille verticale fixe de la zone conteneur.

  3. La solution <br... de W3C
  4. Le World Wide Web Consortium (W3C) aurait suggéré d'ajouter une balise <br> avec le style clear:both avant le paragraphe contenant la seconde date.

    <div style="width:90%; border:1px solid green; margin-left:auto; margin-right:auto"> <p style="text-align:center">date: 2018-02-03</p> <div style="float: left; width:40%; border:1px solid red"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse. </div> <div style="float: right; width:40%; border:1px solid blue"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam. </div> </div> <br style="clear:both"/> <p style="text-align:right; border:1px solid #aaa; margin:0; padding:0">date: 2018-02-04</p>

    Au moins, la seconde date est située sous les zones de texte flottantes qu'importe leur hauteur alors qu'on modifie la largeur de la fenêtre du fureteur.



    date: 2018-02-03

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam.

    date: 2018-02-04


    Cette solution n'est pas parfaite. Par exemple, le cadre dessiné autour du conteneur initial n'englobe pas les deux zones flottantes. De plus il faut ajouter un élément structurant la présentation visuel au texte HTML. C'est quelque chose à éviter surtout depuis l'introduction des styles CSS.

  5. La solution clearfix
  6. On peut remplacer <br style="clear:both"> avec un <div> qui a le même attribut clear et qui occupe la pleine largeur de son contenant, mais qui n'a aucune dimension verticale.

    <div style="width=100%; clear:both; font-size:0">&nbsp;</div>

    On note que la bloc contient un espace insécable &nbsp; mais qui est imprimé avec une police de hauteur 0. C'est une astuce pour s'assurer que tous les navigateurs web tiennent compte de l'élément. Ceci n'apporte rien de mieux à la solution proposée par le W3C, mais il permet de mieux comprendre le style clearfix dont plusieurs variantes existent depuis déjà des années. Parmi celles-ci, j'ai utilisé celle de Jeff Starr proposée en 2005 et révisée en 2017 puisqu'elle était la plus récente de celles que j'avais trouvées.

    .clearfix:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; } .clearfix { display: block; }

    Le principe de fonctionnement est le suivant. Le bloc <div> contenant les zones flottantes sera de classe clearfix. Cette classe possède un pseudo élément after qui insère un contenu après que le <div> ai été affiché. Et ce qui est inséré est sommes toutes le <div> à dimension verticale nulle vue ci-dessus.

    <div class="clearfix" style="width:90%; border:1px solid green; margin-left:auto; margin-right:auto"> <p style="text-align:center">date: 2018-02-03</p> <div style="float: left; width:40%; border:1px solid red"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse. </div> <div style="float: right; width:40%; border:1px solid blue"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam. </div> </div> <p style="text-align:right; border:1px solid #aaa; margin:0; padding:0">date: 2018-02-04</p>

    On peut voir que le <div> de classe clearfix ajuste sa hauteur pour englober les zones flottantes.



    date: 2018-02-03

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam.

    date: 2018-02-04



    Références:

    Lessons Learned Concerning the Clearfix CSS Hack
    Jeff Starr, 5 février 2008, révision 15 janvier 2017.
    Clearing Floats: Why is it Necessary Even in “Modern” Browsers?
    Louis Lazaris, 23 octobre2012.
    Utiliser la class clearfix
    Renaud Anney, 16 août 2012
    How To Clear Floats Without Structural Markup
    Big John le 14 mai 2004 révision 2 juillet 2008
    Simple Clearing of Floats
    Alex Walker, 26 févier 2005

  7. Tout était prévu : overflow
  8. En relisant les deux dernières références mentionnées ci-dessus, il semble que la solution était anticipée par l'attribut CSS overflow. Il suffit d'ajouter overflow:auto au style du <div> parent.

    <div style="width:90%; border:1px solid green; margin-left:auto; margin-right:auto; overflow:auto"> <p style="text-align:center">date: 2018-02-06</p> <div style="float: left; width:40%; border:1px solid red"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse. </div> <div style="float: right; width:40%; border:1px solid blue"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam. </div> </div> <p style="text-align:right; border:1px solid #aaa; margin:0; padding:0">date: 2018-02-04</p>

    Cela fonctionne et c'est simple. En revanche, c'est un peu difficile à comprendre puisque le rôle de l'attribut overflow est de gérer l'utilisation des barres de défilement quand le contenu d'un bloc dépasse ses bornes. Il ne m'est pas clair pourquoi c'est la taille du bloc est ajustée. En même temps, il n'est pas clair où il faudrait ajouter une barre de défilement pour voir les zones flottantes déjà visibles.



    date: 2018-02-06

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam, quis nostrud exercitation ullamco laboris nisi utaliquip ex ea commodo consequat. Duis aute irure dolor inreprehenderit in voluptate velit esse.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enimad minim veniam.

    date: 2018-02-04



  9. Le nouveau clearfix moderne
  10. L'avertissement suivant

    « overflow:auto fonctionne bien tant que l'on contrôle les marges extérieures et intérieures (sinon des barres de défilement pourraient apparaître) »
    - traduction libre de
    « The overflow:auto clearfix works well as long as you are able to keep control of your margins and padding (else you might see scrollbars) ».
    est lancé sur la page intitulé CSS Layout - float and clear de w3schools. On trouvera une discussion plus poussée sur les problèmes qui peuvent se présenter avec cette approche dans Clearing floats de Peter-Paul Koch (mars 2005).

    Ce dernier proposait l'élément CSS suivant.

    .clearfix { overflow: hidden; width: 100%; }

    J'avais de la difficulté à comprendre overflow:auto, overflow:hidden n'a pas plus de sens et peut-être même moins. Notez que l'attribut width pourrait être remplacé par un attribut height dont la valeur souvent vue est 1px ou 1%. Il n'est pas nécessaire de fixer la largeur à 100%, d'ailleurs dans l'exemple, la largeur de la zone est 90% de celle de son contenant.

    La solution que w3schools propose elle-même est d'utiliser le pseudo élément suivant.

    .clearfix::after { content: ""; clear: both; display: table; }

    Puisqu'il n'est pas nécessaire d'inclure un attribut quelconque dans le style clearfix, alors ce dernier n'a pas besoin d'être défini; le pseudo-élément suffit. En revanche, on utilisera toujours class="clearfix" dans le fichier HTML.

    On notera le double deux-points pour indiquer le pseudo-élément. Il semble que c'est un changement récent de la syntaxe.

  11. Conclusion
  12. J'ai vérifié toutes ces solutions à l'aide de la page test.html. Elles fonctionnent toutes pour ce qui est du petit problème d'alignement que j'ai présenté ici, qui correspond à ce que j'utilise sur le présent site.

    Pour être plus précis, j'ai examiné la page avec des versions récentes des principaux navigateurs sur les systèmes d'exploitation les plus courants.

    Navigateur Système
    FirefoxWindows 10, Ubuntu 17.1, Android 6
    ChromiumUbuntu 17.1
    ChromeAndroid 6
    EdgeWindows 10
    Internet ExplorerWindows 10
    SafariOSX, IOS

    Bien sûr, il y a d'autres navigateurs et d'autres systèmes d'exploitation. Il y a aussi les version antérieures des navigateurs; les plus anciennes ne se conformaient pas entièrement aux standards W3C. Toutefois, est-ce bien nécessaire de s'assurer la compatibilité avec Firefox 3.5 ? Surtout sur un site comme celui-ci?

    J'ai décidé d'utiliser le clearfix de w3schools parce qu'en principe toutes les recommandations qu'on retrouve sur ce site ont été vérifiées avec plusieurs navigateurs dont certains que je ne possède pas.

    Qu'importe la solution choisie, il me semble préférable de procéder à l'aide d'un style qu'on pourrait appeler clearfix ou autre chose. J'ai lu quelque part qu'on prépare un attribut CSS pour régler ce problème de façon explicite. Si l'on a dispersé des overflow:xxxx dans plusieurs autres styles, il pourrait être plus difficile de passer au nouvel attribut en temps et lieu.