grid layout, vers la grille parfaite

J’ai publié, il y a un peu plus d’un an maintenant, un article nommé « le point sur les grilles en CSS », dans lequel je comparais les différentes techniques permettant de réaliser une grille de mise en forme via les positionnements CSS existants.

La conclusion de cet article était qu’aucun mode de positionnement, même parmi les plus avancés tels que multi-columns, Flexbox ou Grid Layout ne remplissait toutes les conditions de la grille parfaite.

Mais ça, c’était avant que les spécifications de Grid Layout n’évoluent et n’apportent ce qu’il manquait.

Parmi les récents ajouts de Grid Layout, je vous laisse apprécier :

  • la valeur-fonction repeat() permettant d’initialiser une grille répétitive très facilement
  • la répartition automatique des éléments dans la grille (autoflow) sans avoir à les placer individuellement
  • la gestion de gouttières via grid-gap (raccourci de grid-column-gap et grid-row-gap.

The grid

Grâce à ces nouveautés, il est devenu extrêmement simple de construire une grille de 4 colonnes séparées d’une gouttière de 1rem par exemple :

.container {
  display: grid; /* grid container */
  grid-template-columns: repeat(4, 1fr); /* 4 cols repeated, equal width */
  grid-gap: 1rem; /* vertical and horizontal gutter */
}

Éléments double ou triple taille ?

Toujours aussi facilement, il est possible d’indiquer à certains éléments qu’il doivent occuper plusieurs colonnes ou plusieurs lignes :

@media (min-width: 481px) {
  .col-span {
    grid-column: span 2; /* will be double sized horizontally */
  }
  .row-span {
    grid-row: span 2; /* will be double sized vertically */
  }
}

Preums ?

Indiquer à un élément qu’il doit s’afficher avant les autres est tout aussi enfantin :

.first {
  order: -1; /* will be first item */
}

 

Responsive ? Facile !

Un petit coup de Media Queries pour changer la grille suffit pour tout remanier lorsque les tailles d’écrans changent.

Voyez vous-même :

/* Responsive small */
@media (max-width: 640px) {
  .container {
    grid-template-columns: repeat(2, 1fr);
  }
}
/* Responsive tiny */
@media (max-width: 480px) {
  .container {
    grid-template-columns: 1fr;
  }
}

Et hop !

Version écrans larges (4 colonnes) :

grid

Version écrans réduits (2 colonnes) :

grid2

Version écrans petits (1 colonne) :

grid3

Voir l’exemple en ligne
(activez vos flags et testez sur Chrome Canary pour les gouttières)

C’est pour quand ?

La grille parfaite en CSS existe enfin, Bootstrap n’a qu’à bien se tenir, moi je vous le dis !

Il y a juste encore un tout petit souci, celui de la compatibilité. En effet, il n’y a actuellement qu’un seul navigateur qui reconnaisse Grid Layout nativement, c’est …Internet Explorer (10+) / Edge.

Ceci dit, la specification est en pleine implémentation du côté des autres navigateurs / moteurs : Chrome, Opera, Firefox le testent via un flag; sur Safari c’est également en cours de développement.

Bref, l’attente ne sera pas si longue que ça. Le retardataire sera cette fois Safari, qui nous forcera sans doute à attendre que iOS10 soit pleinement démocratisé.

Et sinon, si le coeur vous en dit, il existe un polyfill Grid Layout qui semble prometteur.

Maxibonus : les variables CSS pour oublier définitivement Bootstrap !

Les variables CSS (ou de leur vrai nom « custom properties ») vont élargir les horizons de ce type de grilles, les simplifier et nous permettre de nous débarrasser définitivement des frameworks usines à gaz.

Je vous invite vivement à consulter l’article de Thomas Zilliox « les variables CSS sont nos amies » pour découvrir les possibilités offertes par cette spécification malheureusement encore trop peu supportée par les navigateurs (Firefox uniquement à ce jour).

Nous pourrions automatiser notre code précédent de la formidable manière suivante :

[class*="grid-"] {
  --grid-number: 4;
  --grid-gutter: 1rem;
  display: grid;
  grid-template-columns: repeat(var(--grid-number), 1fr);
  grid-gap: var(--grid-gutter);
}

Bon, jusque là rien de très sexy encore  mais imaginez à présent pouvoir créer vos propres grilles aux valeurs personnalisées, rien qu’en donnant un nom de classe à votre conteneur.

[class*="grid-3"] {
  --grid-number: 3;
}
[class*="grid-2"] {
  --grid-number: 2;
}
...
[class*="-gutter-2"] {
  --grid-gutter: 2rem;
}
[class*="no-gutter"] {
  --grid-gutter: 0;
}
...

Concrètement voici comment on pourrait employer ces variables :

  • un conteneur de classe .grid-2 crée une grille de 2 colonnes, de gouttière 1rem,
  • un conteneur de classe .grid-2-no-gutter crée une grille de 2 colonnes, sans gouttière,
  • un conteneur de classe .grid-gutter-2 crée une grille de 4 colonnes, de gouttière 2rem,

etc.

L’avenir des grilles est en marche !

Livre flexbox, la couverture

ça se précise de plus en plus… :)

flexbox-couverture

et la dernière de couverture (le contraste devrait être meilleur en vrai) :

flexbox-couv4

Merci Eyrolles pour la mise en page et pour l’effort sur le prix  (d’abord annoncé à 26€, mais heureusement baissé à 19.90€) :)

Aux dernières nouvelles, la date de sortie est prévue pour février-mars 2016.

Enlarge ton device avec Windows Phone 10 !

J’ai procédé ce week-end à la mise à jour de Windows Phone 8.1 vers Windows Phone 10 sur mon Nokia Lumia 1020.

Jusqu’alors, sur mon ex-Windows 8.1, l’ensemble de mes navigateurs affichaient des dimensions d’écran similaires :

  • en portrait, largeur d’écran 320px sur IE11, Opera mini, Maxthon et UC Browser
  • en paysage, largeur d’écran 480px sur IE11, Opera mini, Maxthon et UC Browser

(source de test : mydevice.io)

Depuis la mise à jour vers le nouvel OS de Microsoft, quelle ne fut pas ma surprise de constater un certain nombre de modifications quant à la taille d’écran utilisable.

Si les dimensions annoncées en portrait ne changent pas et sont toujours annoncées à 320px sur l’ensemble des navigateurs mobiles, les résultats sont bien plus étonnants dès lors que l’on tourne son device en paysage :

  • IE Edge : largeur d’écran 640px en paysage (contre 480px précédemment)
  • Opera mini : largeur d’écran 568px en paysage (contre 480px précédemment)
  • Maxthon : largeur d’écran 320px en paysage (contre 480px précédemment)
  • UC Browser : largeur d’écran 320px en paysage (contre 480px précédemment)

En résumé :

  • les navigateurs ne renvoient plus résultats identiques entre eux
  • IE Edge lui-même a décidé de modifier sa valeur par rapport à son prédécesseur

Quelles conclusions en tirer ?

Si ce n’était pas déjà le cas, arrêtons de calculer nos breakpoints et nos Media Queries en fonction des devices car cela n’a vraiment aucun sens :

  • il est impossible de cibler tous les device existants,
  • chaque jour de nouveaux devices et de nouvelles valeurs apparaissent,
  • même les devices actuels et reconnus se permettent de muter avec leurs navigateurs.

Bref, établissez vos breakpoints selon votre design et uniquement selon votre design. Il doit pouvoir s’adapter quel que soit le média, sa taille et ses caractéristiques.

Visuel Edge en paysage :

edge

Visuel Opera en paysage :

opera

Visuel Maxthon et UC Browser en paysage :

maxthon.png

Ce bon vieux tableau HTML

Hier, sur Twitter, j’ai conseillé d’utiliser des tableaux HTML pour de la mise en forme. Et je n’ai même pas honte.

En 2011 déjà, lors d’un atelier Paris-Web, je vantais les mérites des tableaux HTML pour de l’habillage graphique.

Au cours de cette présentation, je revenais point par point sur chacun des arguments anti-tableaux :

  • Non, un tableau n’est pas forcément lourd et complexe (rien ne vous impose de les imbriquer),
  • Non, un tableau n’est pas forcément inaccessible (un tableau peut être linéarisé, et il existe de nombreux attributs HTML et ARIA pour rendre un tableau accessible),
  • Non, les tailles des cellules d’un tableau ne sont pas forcément incontrôlables car dépendantes de leur contenu (il existe table-layout: fixed – du CSS1 – pour maîtriser les dimensions des tableaux),
  • Non, le rendu d’un tableau n’est pas forcément lent pour le navigateur (table-layout fait un boulot formidable pour la performance),
  • Oui un tableaux peut être rendu responsive (tout simplement en rendant les cellules en display: block par exemple),
  • Oui, un tableau n’est pas vraiment sémantique (mais les attributs role d’ARIA changent grandement la donne),
  • Oui, le code d’un tableau est souvent superflu pour réaliser des choses simples (nécessité de table, tr, td),
  • Oui utiliser des tableaux de mise en page est obsolète (mais tout autant que d’utiliser des float pour le même résultat).

Bref, l’idée globale de ma présentation était à cette époque de revenir sur le classique « les tableaux HTML, c’est le Mal absolu », tellement ancré dans nos esprits que l’on ne se pose même plus de questions.

En 2015, avec toutes les techniques de positionnement actuels (inline-block, table-cell, flexbox, etc.), et avec tout le mal qu’on a pu dire des tableaux HTML, comment est-il encore possible que j’en parvienne à conseiller son usage ?

Tout simplement parce que l’on m’a demandé comment réaliser ce type de gabarit, a priori très simple :

joli gabarit

Aussi évident que puisse paraître ce gabarit, il est extrêmement complexe à concevoir avec des float, des position: absolute, des inline-block, des table-cell et même avec Flexbox (ce dernier nécessiterait une hauteur globale fixe, ce qui n’est pas souhaité). En tout cas sauf grosses bidouilles ou de conteneurs supplémentaires.
Seul Grid Layout apporte une solution parfaite, mais manque encore de compatibilité.

Selon moi, le meilleur choix, aujourd’hui, est le tableau HTML.

Ce tableau, nous pouvons le rendre à la fois accessible et « sémantique » grâce à l’apport des rôles « landmarks » ARIA.

<table role="presentation">
<!-- surtout pas d'attribut summary -->
  <tr>
    <td rowspan="2" class="aside" role="complementary" >aside</td>
    <td class="nav" role="navigation">navigation</td>
  </tr>
  <tr>
    <td class="main" role="main">main</td>
  </tr>
</table>

Le résultat en ligne : http://codepen.io/raphaelgoetter/pen/XmxNpW?editors=110

Si des spécialistes en CSS ou en Accessibilité ont envie d’intervenir pour améliorer le code ou trouver une autre solution, je prends !

Liste de sites web basés sur Flexbox

Je connais de plus en plus de sites personnels, de blogs et de petites agences web qui sont passés à Flexbox en production.

Par contre, il est bien plus difficile de trouver des références de sites web « célèbres » basés – au moins en partie – sur Flexbox layout.

Grâce à l’aide précieuse de Pascal qui s’est amusé à faire le tri parmi le « Top 1000000 d’Alexa rank », je me suis mis en tête de rassembler ces fameux sites sous forme d’une liste non exhaustive, et surtout participative.

N’hésitez pas à me signaler toute suggestion d’entrée dans cette liste via un commentaire ou un twitt (@goetter) !

Sites internationaux

  • twitter.com
  • nytimes.com
  • flickr.com
  • booking.com
  • mappy.com
  • ft.com
  • walmart.com
  • washingtonpost.com
  • usatoday.com
  • mailchimp.com
  • weather.com
  • codepen.io
  • cma-cgm.com

Sites français

  • liberation.fr
  • paris.fr
  • canalplay.com
  • 6play.fr
  • betaseries.com
  • roquefort-societe.com
  • alsacreations.fr

Note : vous constaterez que de nombreux sites sont encore positionnés en flottants sur leurs versions de bureau, par contre Flexbox prend souvent le relais dès lors que ces sites passent en Responsive

Flexbox a cassé mes images responsive !

En plein tests de mise en page Responsive, et encore tout excité de pouvoir enfin appliquer Flexbox en production, vous serez surpris de constater un phénomène étrange lorsque vous tenterez d’utiliser la célèbre technique suivante pour rendre vos images fluides à l’intérieur de leur parent :

img {
max-width: 100%;
height: auto;
}

Non seulement, l’image ne s’adapte pas à la taille de son parent comme vous l’aviez prévu, mais pire : c’est son parent qui s’adapte aux dimensions initiales de l’image !

Capture d’écran 2015-10-30 à 20.20.33

Il ne s’agit (malheureusement) pas d’un bug mais de l’observation stricte des récentes spécifications de Flexbox.

Pour rappel, les flex-items ont dorénavant par défaut une valeur de min-width (et min-height) définie à « auto », c’est à dire la taille de leur contenu.

Les spécifications sont claires sur ce point : http://www.w3.org/TR/css-flexbox-1/#min-size-auto
Certains éléments dits « remplacés », c’est à dire les éléments img, video, picture, canvas, textarea, input, etc. possèdent des dimensions intrinsèques.

Leur parent flex-item en vertu de sa nouvelle valeur de min-width, calcule sa taille en fonction de cette dimension par défaut, et c’est pourquoi max-width : 100% n’aura aucun effet… puisque c’est l’image elle-même qui détermine la taille de son parent.

Il existe deux méthodes simples pour éviter ce piège et rendre nos images fluides :

  1. min-width: 0; sur le parent flex-item de l’image.
    En effet, muni d’une valeur explicite de min-width, il n’adopte plus la valeur par défaut « auto », problématique.
  2. flex-direction : column sur le flex-container.
    En basculant dans un axe vertical, c’est la hauteur minimum (min-height) qui est alors calculée en fonction du contenu et non plus la largeur.
  3. EDIT : overflow: hidden (ou auto ou scroll) sur le flex-item (merci Jonathan).

Vous pouvez tester en live ici (pour l’instant, seul Firefox respecte la spec… et donc pose un problème) :