Défi et limitation de la Flexbox
Le défi consiste à centrer un groupe d'éléments flexibles et à les aligner à gauche sur l'enveloppe. Mais à moins qu'il n'y ait un nombre fixe de boîtes par ligne et que chaque boîte soit de largeur fixe, ce n'est actuellement pas possible avec flexbox.
En utilisant le code publié dans la question, nous pourrions créer un nouveau conteneur flex qui encapsule le conteneur flex actuel ( ul
), ce qui nous permettrait de centrer le ul
avec justify-content: center
.
Ensuite, les éléments flexibles du ul
peuvent ê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 flexibles alignés à gauche.
Le problème avec cette méthode est qu'à certaines tailles d'écran, il y aura un espace sur la droite du ul
, ce qui le fera ne plus apparaître centré.
Cela se produit parce que dans la mise en page flex (et, en fait, CSS en général), le conteneur:
- ne sait pas quand un élément s'enroule;
- ne sait pas qu'un espace précédemment occupé est maintenant vide, et
- ne recalcule pas sa largeur pour réduire la mise en page la plus étroite.
La longueur maximale de l'espace blanc sur la droite est la longueur de l'élément flexible que le conteneur s'attendait à y trouver.
Dans la démo suivante, en redimensionnant la fenêtre horizontalement, vous pouvez voir les espaces aller et venir.
DEMO
Une approche plus pratique
La mise en page souhaitée peut être obtenue sans flexbox inline-block
ni requêtes multimé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;
width: 1200px;
padding-left: 0;
font-size: 0;
}
li {
display: inline-block;
font-size: 18px;
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 rend un conteneur centré horizontalement avec des éléments enfants alignés à gauche comme ceci:
DEMO
Autres options
margin:0 auto
sur un wrapper parent, de sorte que tout soit centré sur la page. À partir de là, tous les composants enfants, (c'est-à-dire le premier conteneur flexible) se contentent de suivre son processus de ligne de flux normal? On dirait que cela pourrait être simple à faire.Vous pouvez y parvenir avec CSS Grid, utilisez simplement
repeat(autofit, minmax(width-of-the-element, max-content))
ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, max-content)); grid-gap: 16px; justify-content: center; padding: initial; } li { list-style-type: none; border: 1px solid gray; padding: 5px; width: 210px; }
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> </ul>
http://jsfiddle.net/rwa20jkh/
la source
justify-items: center
pourjustify-content:center
, et maintenant il se concentre parfaitement.210px
partie à l'intérieurminmax
. Comment puis-je du même mais sans restriction artificielle de210px
? Il n'y a pas une telle restriction avec flexbox. Je veux exactement le même résultat qu'avec flexbox, mais la zone de contenu doit être centrée comme dans votre solution.width:200px
, et dans mon exemple, comme je l'ai indiquéwidth:210px
, je dois ajouter cela également dans laminmax
partieComme @michael l'a suggéré, il s'agit d'une limitation avec la flexbox actuelle. Mais si vous souhaitez toujours utiliser
flex
etjustify-content: center;
, nous pouvons contourner le problème en ajoutant unli
élément factice et en attribuantmargin-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 ce violon (redimensionner et voir) ou vidéo pour référence
la source
Une façon d'obtenir le style souhaité avec des marges est de procéder comme suit:
#container { display: flex; justify-content: center; } #innercontainer { display: flex; flex: 0.9; -> add desired % of margin justify-content: flex-start; }
la source
Vous pouvez placer des éléments invisibles avec la même classe que les autres (supprimés sur exemple à des fins d'exposition) et une hauteur fixée à 0. Avec cela, vous pourrez justifier les éléments au tout début de la grille.
Exemple
<div class="table-container"> <div class="table-content"> <p class="table-title">Table 1</p> <p class="mesa-price">$ 20</p> </div> <!-- Make stuff justified start --> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> </div>
Résultat
la source
J'ai rencontré ce problème lors du codage avec React Native. Il existe une solution élégante que vous pouvez avoir en utilisant FlexBox. Dans ma situation particulière, j'essayais de centrer trois boîtes flexibles (Flex: 2) dans une autre en utilisant alignItems. La solution que j'ai trouvée consistait à utiliser deux s vides, chacun avec Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}> <View style={{flex: 1}} /> // Content here <View style={{flex: 1}} /> </View>
Assez facile à convertir en web / CSS.
la source