Flexbox Quiz

Dans la même veine que le « Quiz CSS » posté il y a maintenant quelques années par Thierry Koblentz, je vous propose un Quiz Flexbox.

La question est : parmi l’ensemble des déclarations suivantes, lesquelles n’ont pas d’effet ?
(dans le sens « lesquelles ne s’appliquent pas ou bien reproduisent inutilement la valeur par défaut »).

Notes :

  • la page ne contient que ces styles et rien d’autre, et les éléments ciblés existent dans le DOM (edit: et ne sont pas des tableaux).
  • le code doit pouvoir fonctionner avec un ou plusieurs flex-items.
  • si une propriété s’applique, si elle impacte le comportement, il faut la conserver.
  • le code est à tester sur un navigateur moderne ne présentant pas de bug majeur sur Flexbox (donc pas IE10 et IE11)
  • ne cherchez pas trop sur Google et ne testez pas tout de suite le code sur une vraie page, sinon il n’y a plus de plaisir 😉
.flex-container {
  display: flex;
  flex-flow: column nowrap;
  align-items: space-between;
  flex-direction: row;
}

.flex-item {
  flex: 1;  
  display: block;
  align-content: center;
  flex-shrink: 1;
  float: left;
  clear: both;
  z-index: -1;
  bottom: 1em;
  vertical-align: top;
  width: 250px;
  height: 250px;
}

Laissez-moi vos réponses par commentaires.

Je donne le corrigé explicatif très prochainement.


Correction et explications.

Voici donc le verdict. Je préviens qu’il y avait forcément pas mal de pièges et que j’avoue que l’énoncé n’était pas toujours très clair. L’essentiel demeurait de participer et de découvrir des choses méconnues.

La réponse la plus proche, munie des explications les plus complètes vient de Loïc Giraudel, bravo à lui !

Sur le .flex-container :

  • display: flex; (à conserver)
    c’est le postuat de départ sans lequel rien ne s’affiche correctement. On garde forcément.
  • flex-flow: column nowrap; (inutile)
    column sera écrasé plus bas par flex-direction et nowrap est la valeur par défaut.
  • align-items: space-between (inutile)
    ne s’appliquera jamais… puisque space-between n’est pas une valeur autorisée pour align-items (très peu y ont prêté attention).
  • flex-direction: row; (inutile)
    row est la valeur par défaut, bref on retourne à l’état initial d’un flex-container.

Sur le .flex-item :

  • flex: 1; (à conserver)
    permet au flex-item d’être fluide, correspond à flex: 1 1 0; (la valeur par défaut étant flex: initial;, soit flex: 0 1 auto;)
  • display: block; (inutile)
    presque aucune valeur de display n’est prise en compte sur un flex-item (sauf none et flex, et sauf bugs sur IE10-IE11).
  • align-content: center; (inutile)
    cette propriété ne s’applique que sur un flex-container.
  • flex-shrink: 1; (inutile)
    il s’agit de la valeur par défaut de flex-shrink et elle n’entre pas en contradiction avec la déclaration précédente flex: 1;, elle est donc inutile.
  • float: left; (inutile)
    la propriété float ne s’applique pas à un flex-item.
  • clear: both; (inutile)
    la propriété clear ne s’applique pas à un flex-item.
  • z-index: -1; (à conserver !)
    c’est assez inattendu, mais un flex-item crée un « stacking context » et la propriété z-index s’y applique. Il est donc nécessaire de conserver cette déclaration car elle peut modifier le comportement de l’élément et de son environnement (dans le code initial, j’avais z-index:0; mais l’argument reste le même).
  • bottom: 1em; (inutile)
    la propriété bottom ne s’applique qu’aux éléments positionnés, or un flex-item ne l’est pas par défaut, elle est donc ignorée ici.
  • vertical-align: top; (inutile)
    la propriété vertical-align ne s’applique pas à un flex-item.
  • width (inutile)
    est écrasé par flex-basis: 0, prioritaire, et contenu dans la déclaration flex: 1 (qui pour rappel vaut flex: 1 1 0;)
  • height n’est pas écrasé par flex-basis: 0 car ce dernier n’agit que sur l’axe principal (row ici), donc cette propriété s’applique.

Au final, voici ce qu’on conserve :

.flex-container {
 display: flex;
 }

.flex-item {
 flex: 1;
 z-index: -1;
 height: 250px;
 }

Merci à tous ceux qui ont joué, encore désolé si l’énoncé n’était pas toujours très clair (entre les propriétés qui ne s’appliquent pas, celles qui ne servent à rien), et j’espère que vous y avez appris des trucs !

35 réflexions au sujet de « Flexbox Quiz »

  1. Bonjour,
    Allez, je me lance :
    – Dans .flex-container pas de flex-direction: row car valeur contraire à flex-flow.
    – Dans .flex-item pas de display : block car nous sommes dans le mode flex .
    – align-content est pour le parent .flex-container donc pas nécessaire ici…
    – flex-shrink: 1; est une répétition de flex: 1 (vaut 1 1 0%)
    – Nous sommes dans le cas d’item flex donc ‘float’, ‘clear’, ‘vertical-align’, ‘z-index’ n’auront pas d’effet

  2. Hello,

    J’essaye aussi!

    flex-direction redondant avec flex-flow
    display: block inutile puisque flex
    align-content ne marche que sur les containers
    float et clear inutiles puisque flex
    z-index et bottom inutiles puisque positionnement static (par défaut)
    width pourrait être géré avec la propriété shorthand flex

  3. Hello,
    Allez tentons, mais je sens que je vais dire de grosses conneries. En fait, j’ai toujours du mal avec ce genre de quiz, parce que si on part du postulat display:flex ou si on l’enlève, ce n’est pas pareil…

    Voilà mon retour:

    .flex-container {
      display: flex; /* OK, postulat de base */
      flex-flow: column nowrap; /* OK, sauf qu'ensuite on trouve `flex-direction: row` donc `row nowrap` étant la valeur par défaut, on peut supprimer  */
      align-items: space-between; /* si `nowrap`, une seule ligne donc on peut supprimer */
      flex-direction: row; /* OK */
    }
    
    .flex-item {
      flex: 1; /* OK */
      display: block; /* je dirais utile quand même */
      align-content: center; /* j'avoue ne plus trop savoir. Pour moi, align-content ne s'applique qu'à des blocs de lignes donc n'aurait aucun intérêt ici: inutile */
      flex-shrink: 1; /* inutile car flex:1 == flex: 1 1 0; */
      float: left; /* je dirais inutile */
      clear: both; /* je dirais inutile aussi */
      z-index: 1; /* inutile car pas d'autres éléments, ni autres styles */
      bottom: 0; /* inutile car pas de position absolute */
      vertical-align: top; /* pas sur que ce soit pris en compte, mais je dirais utile */
      width: 250px; /* à priori inutile car flex-grow:1 et flex-shrink:1 */
      height: 250px; /* OK */
    }
    
    1. Bon je sais maintenant qu’il y a d’autres erreurs, mais flex-direction: row; c’est un oubli, la déclaration est bien entendu inutile (cf. commentaire flex-flow)

      Mais en lisant les autres commentaires, je vois que je ne suis pas le seul à faire des postulats, qui influent sur nos réponses. 🙂

  4. ok, je me lance. Je pars du principe qu’il y a plus d’un element « flex-item » parce que si il n’y en avait qu’un on pourrait faire au minimum pour créer une simple boite qui fait 250px de haut et prend toute la largeur de son parent.

    Les déclarations qui me paraissent superflues pour « flex-item »: display, align-content, flex-shrink (because of width), float, clear, z-index, bottom, vertical-align, and width (because of flex:1).
    Celles pour « flex-container »: align-items, mais après ça je ne suis pas sûr pour flex-flow and flex-direction. C’est la cascade qui décide?

    1. Je me rends compte que j’assume un truc qui n’est pas nécessairement vrai (?). Si il y a d’autres elements, le fait d’enlever la déclaration « z-index » changera the stacking context. Donc pour celle-ci, « ça dépend » 😉

    2. Héhé, réponse demain ou après-demain ? 😉
      PS : pour « flex-shrink (because of width) », en fait flex-shrink est prioritaire sur width, non l’inverse

  5. Hello,

    alors sans avoir lu les commentaires précédents et en partant du postulat que le rendu visuel doit être identique au code initial, je garderai :

    .flex-container {
    display: flex;
    }
    .flex-item {
    flex: 1;
    height: 250px;
    }

    Pour le flex-container :
    – flex-direction: row écrase flex-flow: column nowrap;
    – flex-wrap est par défaut à nowrap;
    – align-items: space-between; ne servira à rien étant donné qu’il n’y aura qu’une seule ligne sur l’axe principal. (pas de retour à la ligne)

    Pour les flex-item :
    – display: block; ne servira visuellement à rien même si par défaut son modèle est de type inline-block.
    – align-content: center; ne s’applique que pour du Multi-lignes.
    – flex-shrink: 1; est la valeur par défaut d’un flex item (flex: 0 1 auto;)
    – float: left; et clear: both; ne s’appliquent pas pour des flex items.
    – z-index: 1; donc la ça dépend, je l’ai enlevé car dans l’exemple ça ne changera rien visuellement mais j’ai appris ce matin sur css-tricks que par défaut un flex item se comporte comme un inline-block en position relative; Il possède un contexte d’empilement. z-index peut donc être applicable à un flex item sans posséder de position relative.
    – bottom: 0; ne servira à rien non plus pour un élément relatif. (l’Élément restera à la même place)
    – width: 250px; sera écrasé par le flex: 1;

    Voila, en espérant ne pas avoir raconter trop de bêtises 🙂

      1. Je pense également que le computed value est block, mais il a un design de inline-block (affichage aligné et taille du contenu)

  6. Bon, je teste….

    flex-flow et flex-direction sont inutiles, ils définissent les valeurs par défaut.

    float, clear et vertical-align sont ignorés avec flex.
    z-index et bottom ne sont pris en compte que si on utilise du positionnement absolu/relatif/fixé, c’est pas le cas ici

    Le « display: block » ne me semble pas utile.

    Le width ne semble pas utile que l’élément va grossir ou rétrécir en fonction des besoins, au pire on pourra simplifier « width » et « shrink » avec un « flex: 1 1 250px »

    Ça donnerait un truc comme ça.

    .flex-container {
    display: flex;
    align-items: space-between;
    }

    .flex-item {
    flex: 1 1 250px;
    height: 250px;
    }

    1. Attention, il ne faut pas modifier les déclarations existantes, juste supprimer celles qui ne s’appliquent pas.

  7. Je crois bien que personne n’a exactement la bonne solution, même si certains sont très proches. Je précise bien lesquelles ne s’appliquent pas. Si une propriété s’applique, il faut la conserver.

    Notez qu’il y a un petit détail que personne n’a encore remarqué 😉

    1. C’est bien le problème. Entre ce qui DOIT et ce qui DEVRAIT rester, il y a un monde. C’est par exemple pour ça que j’ai mis une différence entre z-index et bottom. Mais je suis impatient de voir ta solution, j’ai trouvé des cas vraiment sioux. 🙂

  8. C’est ce que je dis. Mais je suis parti du postulat: « lesquelles ne servent à rien ». Si on part du postulat : « lesquelles ne s’appliquent pas », alors il faut en supprimer moins que prévu.

    1. Disons alors « quelles propriétés peuvent êtres supprimées sans qu’il n’y ait aucune incidence sur l’affichage et le comportement des éléments » (un stacking contexte étant une modification du comportement)

  9. .flex-container {
      display: flex;
     /* flex-flow: column nowrap; inutile car écrasé par flex-direction: row qui est valeur par défaut*/
      /*align-items: space-between; */
      /* flex-direction: row; valeur par défaut */
    }
    
    .flex-item {
      flex: 1; 
      /* display: block; */
      /* align-content: center; pour un container ... sauf si on mixe...  */
      /* flex-shrink: 1; default sauf IE out of the game */
      /* float: left; */
      /* clear: both; car tu précises seuls styles de la page, donc pas de float */
      z-index: 1; 
     /* bottom: 0; */
     /* vertical-align: top; */
      /* width: 250px; surchargé par flex : 1*/
      height: 250px; /* height c'est le mal !!! */
    }
    

    avec height, il peut y avoir de l’overflow donc z-index doit jouer

    les réponses ci-dessus : si on accepte pas d’enfants de .flex-container sans classe .flex-item ou de doublon .flex-container.flex-item etc. là… surchauffe !

    j’aurais des doutes avec des img.flex-item et le width (chrome et Fx agiraient de manières différentes ?)

  10. Bonjour à tous,

    .flex-container {
    display: flex;
    flex-flow: column nowrap; // comportement par défaut
    align-items: space-between;
    flex-direction: row; // comportement par défaut
    }

    .flex-item {
    flex: 1; // pour moi comportement par défaut
    display: block; // inutile positionnement parent flex
    align-content: center;
    flex-shrink: 1; // inutile
    float: left; // inutile positionnement parent flex
    clear: both; // mais pourquoi donc ?
    z-index: 1; // inutile vous avez vu du chevauchement quellques part
    bottom: 1em; // inutile ???
    vertical-align: top; // comportement par défaut
    width: 250px; // flexible en largeur
    height: 250px; // inutile car flexible selon le contenu
    }

    Alors je pense que l’on peut faire le ménage pour que cela donne au final :

    .flex-container {
    display: flex;
    align-items: space-between;
    }

    .flex-item {
    align-content: center;
    }

    J’espère avoir bien intégrer ton livre Raphaël (même si je galère encore avec la notion des flex-shrink et flex-grow) et avoir bien fais mes devoirs.

    1. flex: 1; // pour moi comportement par défaut –> houla, non malheureux, ce n’est pas le comportement par défaut !

    2. .flex-container {
        display: flex;
        flex-flow: column nowrap; // peut sauter : "column" sera écrasé par flex-direction et nowrap et le comportement par défaut
        align-items: space-between; // peut sauter : space-between est une valeur de justify-content, pas de align-items
        flex-direction: row; // peut sauter : valeur par défaut
      }
      
      .flex-item {
        flex: 1;  
        display: block; // peut sauter : ne sera pas pris en compte
        align-content: center; // peut sauter : sans effet, c'est supposé être une propriété du container
        flex-shrink: 1; // peut sauter : valeur par défaut
        float: left; // peut sauter : ne sera pas pris en compte
        clear: both; // peut sauter : ne sera pas pris en compte
        z-index: -1;
        bottom: 1em; // peut sauter : ne sera pas pris en compte
        vertical-align: top; // peut sauter : ne sera pas pris en compte
        width: 250px; // peut sauter : le container étant en display:flex et les items en flex-grow:1, les items vont se redimensionner sans prendre en compte le width
        height: 250px;
      }
      

      Reste plus grand chose en définitive 🙂

  11. Hello.
    Au final:
    – je n’avais pas percuté sur le space-between avec align-items. Vicieux !
    – le z-index pour moi devait être enlevé car différence entre celles qui s’appliquent et celles qui ne servent à rien. Mais je savais pour le stacking context.
    vertical-align, là j’en savais rien, mais sur un malentendu…

    Par contre, il reste 2 cas : display et width :
    display, je me suis dit que certains éléments devaient ne pas utiliser block par défaut, et que donc il était utile de le garder. Et effectivement, par exemple avec un table.flex-item, sans display:block, il ne prends pas la taille restante. Bug ou feature ?
    width, j’ai dit que c’était inutile, tout en gardant en tête que width peut être la valeur préférée (par défaut) dans certains cas, et qu’elle était aussi en jeu pour les éléments remplacés et qui ont un ratio à respecter. Après quelques tests, il y a des différences entre Chrome et Firefox. Dans Chrome, width peut avoir un impact sur la taille des <imgs>, <iframe>, surement d’autres éléments aussi (<input>, <fieldset>, etc.). Tu as des infos ?

    Le bin pour tester ça: http://jsbin.com/baxixu/edit?css,output

    1. Hello et merci pour cette analyse détaillée.

      • point 1 : je pense que ce qui dérange dans le <table> est qu’il possède des <tbody>, <tr>, etc. qui ont tous les valeurs de display exotiques. Du coup, même si le <table> est bien un flex-item, sa descendance casse un peu le contexte. Ceci dit, tu as raison : toutes les valeurs semblent fonctionner sur cet élément… sauf display: table
      • point 2 : c’est le cas classique du min-width: auto sur les éléments « inline remplacés » : https://blog.goetter.fr/2015/10/30/flexbox-a-casse-mes-images-responsive/ Il suffit de rajouter min-width: 0 sur le flex-item en effet, mais c’est un peu tiré par les cheveux 😉
      1. Point 1 : Oui display: table « casse » le flex. Je l’ai supposé en me fiant à ce tableau, mais dans le contexte Flexbox, je n’en savais rien. Après lecture de la spec, il semble que la même règle s’applique.
        Point 2, OK, donc c’est bien un bug.

        En tout cas merci, tu m’auras bien fait chercher les cas tricky. 😉

    2. Le cas table est intéressant. Comme mentionné dans ma réponse à Jonathan, je m’attendrais à ce que la « computed value » soit block, pas table. Dans l’example avec l’image, la « computed value » pour cette dernière est block; et cela même si on lui applique display:inline-block.
      Dans mon esprit, display est donc supposé prendre une valeur définie (block) quelque soit le style de l’élément (comme le fait float avec none). Voir « blockification »: https://www.w3.org/TR/css-display-3/#blockification
      Mais ça n’a pas l’air d’être le cas ici avec table.
      Si je m’intéressais plus que ça a flexbox je ferais des recherches mais là je compte plutôt sur Raphaël pour des éclaircissements. Alors bug ou pas bug?

Les commentaires sont fermés.