Wyzwanie i ograniczenia dotyczące Flexbox
Wyzwaniem jest wyśrodkowanie grupy elementów elastycznych i wyrównanie ich w lewo na zawijaniu. Ale jeśli nie ma stałej liczby pudełek w rzędzie, a każde pudełko ma stałą szerokość, nie jest to obecnie możliwe w przypadku Flexbox.
Korzystając z kodu zamieszczonego w pytaniu, moglibyśmy utworzyć nowy kontener flex, który otacza obecny kontener flex ( ul
), co pozwoliłoby nam wyśrodkować ul
z justify-content: center
.
Następnie elementy flex ul
można wyrównać do lewej z justify-content: flex-start
.
#container {
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: flex-start;
}
Tworzy to wyśrodkowaną grupę elementów elastycznych wyrównanych do lewej.
Problem z tą metodą polega na tym, że przy pewnych rozmiarach ekranu będzie luka po prawej stronie ul
, przez co nie będzie już wyglądać na wyśrodkowaną.
Dzieje się tak, ponieważ w układzie flex (a właściwie ogólnie w CSS) kontener:
- nie wie, kiedy element się zawija;
- nie wie, że zajmowane wcześniej miejsce jest teraz puste, i
- nie oblicza ponownie swojej szerokości, aby zawijać węższy układ.
Maksymalna długość odstępu po prawej stronie to długość elementu elastycznego, którego oczekiwał kontener.
W poniższym demo, zmieniając rozmiar okna w poziomie, możesz zobaczyć pojawianie się i znikanie białych znaków.
PRÓBNY
Bardziej praktyczne podejście
Żądany układ można osiągnąć bez użycia flexboxa inline-block
i zapytań o media .
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; } }
Powyższy kod renderuje kontener wyśrodkowany w poziomie z elementami potomnymi wyrównanymi do lewej, takimi jak ten:
PRÓBNY
Inne opcje
margin:0 auto
opakowania nadrzędnego, aby wszystko było wyśrodkowane na stronie. Od tego momentu wszystkie komponenty podrzędne (tj. Pierwszy kontener elastyczny) po prostu wykonują normalny proces przepływu wiersza? Wydaje się, że można to uprościć.Możesz to osiągnąć za pomocą siatki CSS, po prostu użyj
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/
źródło
justify-items: center
najustify-content:center
, a teraz idealnie się centruje.210px
części w środkuminmax
. Jak zrobić to samo, ale bez sztucznego ograniczenia210px
? W przypadku flexbox nie ma takiego ograniczenia. Chcę dokładnie tego samego wyniku co w przypadku flexboksa, ale obszar zawartości musi być wyśrodkowany tak, jak w twoim rozwiązaniu.width:200px
, aw moim przykładzie, tak jak ustawiłemwidth:210px
, muszę to dodać również wminmax
częściJak zasugerował @michael, jest to ograniczenie w obecnym flexboksie. Ale jeśli nadal chcesz używać
flex
ijustify-content: center;
, możemy to obejść, dodającli
element fikcyjny i przypisującmargin-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);
Sprawdź to skrzypce (zmień rozmiar i zobacz) lub wideo w celach informacyjnych
źródło
Jednym ze sposobów uzyskania pożądanego stylu z marginesami jest wykonanie następujących czynności:
#container { display: flex; justify-content: center; } #innercontainer { display: flex; flex: 0.9; -> add desired % of margin justify-content: flex-start; }
źródło
Możesz umieścić niewidoczne elementy z tą samą klasą co pozostałe (usunięte np. Na potrzeby wystawy) i wysokością ustawioną na 0. Dzięki temu będziesz mógł wyrównać pozycje na samym początku siatki.
Przykład
<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>
Wynik
źródło
Napotkałem ten problem podczas kodowania w React Native. Jest eleganckie rozwiązanie, które możesz mieć używając FlexBox. W mojej konkretnej sytuacji próbowałem wyśrodkować trzy pola flex (Flex: 2) wewnątrz innego za pomocą alignItems. Rozwiązanie, które wymyśliłem, polegało na użyciu dwóch pustych s, każdy z Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}> <View style={{flex: 1}} /> // Content here <View style={{flex: 1}} /> </View>
Wystarczająco łatwe do konwersji na web / CSS.
źródło