web-dev-qa-db-fra.com

Comment centrer un conteneur Flex mais des éléments flex alignés à gauche

Je veux que les éléments flex soient centrés mais quand nous avons une deuxième ligne, avoir 5 (de l'image ci-dessous) sous 1 et non centré dans le parent.

enter image description here

Voici un exemple de ce que j'ai:

ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: 0;
}
li {
  list-style-type: none;
  border: 1px solid gray;
  margin: 15px;
  padding: 5px;
  width: 200px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

http://jsfiddle.net/8jqbjese/2/

64
CoachNono

Flexbox Challenge & Limitation

Le défi consiste à centrer un groupe d’articles flexibles et à les aligner à gauche. Toutefois, à moins d’un nombre fixe de boîtes par ligne et que chaque boîte ait une largeur fixe, cela n’est actuellement pas possible avec flexbox.

En utilisant le code affiché dans la question, nous pourrions créer un nouveau conteneur flex qui enveloppe le conteneur flex actuel (ul), ce qui nous permettrait de centrer le ul avec justify-content: center.

Ensuite, les éléments flexibles de ul pourraient être alignés à gauche avec justify-content: flex-start.

#container {
    display: flex;
    justify-content: center;
}

ul {
    display: flex;
    justify-content: flex-start;
}

Cela crée un groupe centré d'éléments flex alignés à gauche.

Le problème avec cette méthode est qu’à certaines tailles d’écran, il y aura un espace à droite du ul, ce qui le rendra plus centré.

enter image description hereenter image description here

Cela se produit parce que, dans la mise en page flex (et, en fait, CSS en général), le conteneur:

  1. ne sait pas quand un élément se termine;
  2. ne sait pas qu'un espace précédemment occupé est maintenant vide, et
  3. ne recalcule pas sa largeur pour réduire la mise en page plus étroite.

La longueur maximale des espaces blancs à droite est la longueur de l'élément flexible que le conteneur s'attendait à trouver.

Dans la démonstration suivante, en redimensionnant la fenêtre horizontalement, vous pouvez voir les espaces aller et venir.

[~ # ~] démonstration [~ # ~]


Une approche plus pratique

La mise en page souhaitée peut être réalisée sans flexbox avec inline-block et requêtes sur les médias.

HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

CSS

ul {
    margin: 0 auto;                  /* center container */
    width: 1200px;
    padding-left: 0;                 /* remove list padding */
    font-size: 0;                    /* remove inline-block white space;
                                        see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 18px;                 /* restore font size removed in container */
    list-style-type: none;
    width: 150px;
    height: 50px;
    line-height: 50px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

Le code ci-dessus affiche un conteneur centré horizontalement avec des éléments enfants alignés à gauche, comme suit:

enter image description here

[~ # ~] démonstration [~ # ~]


Autres options

60
Michael_B

Comme @michael l'a suggéré, il s'agit d'une limitation avec la flexbox actuelle. Mais si vous voulez toujours utiliser flex et justify-content: center;, nous pouvons contourner ce problème en ajoutant un élément factice li et en affectant margin-left.

    const handleResize = () => {
        const item_box = document.getElementById('parentId')
        const list_length  = item_box.clientWidth
        const product_card_length = 200 // length of your child element
        const item_in_a_row = Math.round(list_length/product_card_length)
        const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
        const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin 
        const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
        dummy_product.style.marginLeft = `${left_to_set}px`
    }
    handleResize() // Call it first time component mount
    window.addEventListener("resize", handleResize); 

Vérifiez ceci violon (redimensionner et voir) ou vidéo pour référence

0
RameshVel