Flexbox: 4 elementy w rzędzie


260

Korzystam z okna elastycznego, aby wyświetlić 8 elementów, które będą dynamicznie zmieniać rozmiar na mojej stronie. Jak zmusić go do podzielenia przedmiotów na dwa rzędy? (4 na rząd)?

Oto odpowiedni wycinek:

(Lub jeśli wolisz jsfiddle - http://jsfiddle.net/vivmaha/oq6prk1p/2/ )

.parent-wrapper {
  height: 100%;
  width: 100%;
  border: 1px solid black;
}
.parent {
  display: flex;
  font-size: 0;
  flex-wrap: wrap;
  margin: -10px 0 0 -10px;
}
.child {
  display: inline-block;
  background: blue;
  margin: 10px 0 0 10px;
  flex-grow: 1;
  height: 100px;
}
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>


16
[Aktualizacja] To pytanie było oparte na słabym, niereagującym projekcie. Jeśli znajdziesz jedną z poniższych odpowiedzi, zachowaj ostrożność. Przy dobrym projekcie będziesz mieć więcej przedmiotów na szerszych ekranach, a mniej na mniejszych ekranach. Wymuszenie 4 elementów dla wszystkich rozmiarów ekranu będzie wyglądać atrakcyjnie tylko w wąskim zakresie szerokości ekranu.
— Vivek Maharajh

Odpowiedzi:


380

Masz flex-wrap: wrapna pojemniku. To dobrze, ponieważ zastępuje wartość domyślną, którą jest nowrap( źródło ). Z tego powodu w niektórych przypadkach elementy nie są zawijane, aby utworzyć siatkę .

W tym przypadku głównym problemem są flex-grow: 1elementy elastyczne.

flex-growNieruchomość nie faktycznie wielkości flex przedmiotów. Jego zadaniem jest dystrybucja wolnej przestrzeni w kontenerze ( źródle ). Niezależnie od tego, jak mały jest rozmiar ekranu, każdy element otrzyma proporcjonalną część wolnego miejsca w wierszu.

Mówiąc dokładniej, w twoim pojemniku znajduje się osiem elastycznych przedmiotów. Z flex-grow: 1, każdy otrzymuje 1/8 wolnego miejsca na linii. Ponieważ w twoich przedmiotach nie ma treści, mogą się one zmniejszyć do zera i nigdy się nie zawiną.

Rozwiązaniem jest zdefiniowanie szerokości elementów. Spróbuj tego:

.parent {
  display: flex;
  flex-wrap: wrap;
}

.child {
  flex: 1 0 21%; /* explanation below */
  margin: 5px;
  height: 100px;
  background-color: blue;
}
<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Po flex-grow: 1zdefiniowaniu w flexskrócie nie ma potrzeby, flex-basisaby wynosić 25%, co w rzeczywistości spowodowałoby trzy pozycje z rzędu ze względu na marginesy.

Ponieważ flex-growzajmie wolne miejsce w rzędzie, flex-basismusi być wystarczająco duże, aby wymusić zawijanie. W tym przypadku z flex-basis: 21%marginesami jest dużo miejsca, ale nigdy nie ma wystarczającej ilości miejsca na piąty przedmiot.


1
Podoba mi się to, ponieważ działało dla mnie, ale „dużo miejsca” sprawia, że ​​czuję się trochę nieswojo. Czy jest jakieś małe okno lub sytuacja, w której to „oszacowanie” może mnie zawieść?
— Jackson

1
Jaka sytuacja? W większości układów występują skrajne przypadki, które mogą powodować problemy. Takie przypadki zwykle podlegają analizie kosztów i korzyści, ponieważ nigdy nie występują lub prawie nigdy nie występują. Na przykład w powyższym rozwiązaniu układanie bardzo dużych marginesów może spowodować uszkodzenie układu. Jeśli to jest problem, należy go zamieścić w pytaniu. @Jackson
— Michael Benjamin

2
„Jeśli wprowadzisz bardzo duże marginesy, układ może się zepsuć” To przykład scenariusza, którego chciałbym uniknąć. Nie dbam o praktyczność; baw się uwielbieniem dla doskonałości. Czy jest jakiś sposób, aby być bardziej dokładnym?
— Jackson

27
Możesz także użyćflex: 1 0 calc(25% - 10px);
— MarkG

2
Świetna odpowiedź! Małe ulepszenie, którego używam, to margin: 2%;zamiast stałej liczby pikseli, aby zapobiec przeskakiwaniu pudełek do nowej linii na małych urządzeniach / rozdzielczościach. ogólna formuła to (100 - (4 * box-width-percent)) / 8% dla różnych szerokości skrzynek
— Thomaspsk

104

Dodaj szerokość do .childelementów. Osobiście użyłbym wartości procentowych, margin-leftjeśli chcesz mieć zawsze 4 na wiersz.

PRÓBNY

.child {
    display: inline-block;
    background: blue;
    margin: 10px 0 0 2%;
    flex-grow: 1;
    height: 100px;
    width: calc(100% * (1/4) - 10px - 1px);
}

Dobry pomysł. Użyłem tego pomysłu z niewielkimi zmianami. jsfiddle.net/vivmaha/oq6prk1p/6
— Vivek

1
Ach To tak naprawdę nie rozwiązuje mojego problemu. Zobacz tutaj przykład: jsfiddle.net/vivmaha/oq6prk1p/7 . Nie mogę swobodnie korzystać z procentów dla mojej marży. Muszą mieć stałą szerokość. Oznacza to, że magia 23%, którą wybraliśmy, nie zadziała, ponieważ nie uwzględnia ustalonego marginesu.
— Vivek Maharajh,

3
Tak, calc rozwiązuje to! „calc (100% * (1/4) - 10px - 1px)”. Zobacz jsfiddle.net/vivmaha/oq6prk1p/9
— Vivek

24
Więc w takim razie jaki jest pożytek z flexu?
— twicejr

Co z responsywnym designem? Nie chcemy nakładać stałej szerokości na dziecko
— Candlejack

40

Oto kolejny aplet.

Możesz to zrobić również w ten sposób:

.parent{
  display: flex;
  flex-wrap: wrap;
}

.child{
  width: 25%;
  box-sizing: border-box;
}

Przykład: https://codepen.io/capynet/pen/WOPBBm

I bardziej kompletna próbka: https://codepen.io/capynet/pen/JyYaba


1
Co jeśli mam mniej niż 4 dziecko? Nie podoba mi się to puste puste miejsce, dziecko nie reaguje ...
— candlejack

Druga odpowiedź Muddasira Abbasa wykorzystuje tylko ustawienia flex, więc myślę, że jest to czystsze rozwiązanie.
— Andrew Koster

17

Zrobiłbym to w ten sposób, używając ujemnych marginesów i obliczeń dla rynien:

.parent {
  display: flex;
  flex-wrap: wrap;
  margin-top: -10px;
  margin-left: -10px;
}

.child {
  width: calc(25% - 10px);
  margin-left: 10px;
  margin-top: 10px;
}

Demo: https://jsfiddle.net/9j2rvom4/


Alternatywna metoda siatki CSS:

.parent {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

Demo: https://jsfiddle.net/jc2utfs3/


14
<style type="text/css">
.parent{
    display: flex;
    flex-wrap: wrap;
}
.parent .child{
    flex: 1 1 25%;
}
</style>    
<div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>

Mam nadzieję, że to pomoże. po więcej szczegółów możesz skorzystać z tego linku


4

Uważam, że ten przykład jest bardziej prosty i łatwiejszy do zrozumienia niż @dowomenfart.

.child {
    display: inline-block;
    margin: 0 1em;
    flex-grow: 1;
    width: calc(25% - 2em);
}

Dokonuje się tych samych obliczeń szerokości podczas cięcia bezpośrednio do mięsa. Matematyka jest znacznie łatwiejsza i emjest nowym standardem ze względu na skalowalność i łatwość obsługi mobilnej.


3
nie jest tak naprawdę nowym standardem. To może być bolesne w tyłek, a projektanci nie projektują z myślą o EM.
— Danny van Holten

2

.parent-wrapper {
	height: 100%;
	width: 100%;
	border: 1px solid black;
}
	.parent {
	display: flex;
	font-size: 0;
	flex-wrap: wrap;
	margin-right: -10px;
	margin-bottom: -10px;
}
	.child {
	background: blue;
	height: 100px;
	flex-grow: 1;
	flex-shrink: 0;
	flex-basis: calc(25% - 10px);
}
	.child:nth-child(even) {
	margin: 0 10px 10px 10px;
	background-color: lime;
}
	.child:nth-child(odd) {
	background-color: orange; 
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">

	</style>
</head>
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>
</html>

;)


1
Jeśli możesz dodać kontekst, dlaczego odpowiada na pytanie OP, a nie tylko kod pocztowy.
— d219

jeśli dodasz justify-content: space-evenly;do prenta, to ładnie się dopasują i nie musisz robić tego calcna dziecku. Ale dziękuję za przykład!
— Mattijs

0

Flex wrap + ujemny margines

Dlaczego Flex vs. display: inline-block?

Dlaczego marża ujemna?

Albo używasz SCSS lub CSS-in-JS dla przypadków krawędzi (tj. Pierwszy element w kolumnie), albo ustawiasz domyślny margines i pozbywasz się zewnętrznego marginesu później.

Realizacja

https://codepen.io/zurfyx/pen/BaBWpja

<div class="outerContainer">
    <div class="container">
        <div class="elementContainer">
            <div class="element">
            </div>
        </div>
        ...
    </div>
</div>
:root {
  --columns: 2;
  --betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}

.outerContainer {
    overflow: hidden; /* Hide the negative margin */
}

.container {
    background-color: grey;
    display: flex;
    flex-wrap: wrap;
    margin: calc(-1 * var(--betweenColumns));
}

.elementContainer {
    display: flex; /* To prevent margin collapsing */
    width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
    margin: var(--betweenColumns);
}

.element {
    display: flex;
    border: 1px solid red;
    background-color: yellow;
    width: 100%;
    height: 42px;
}

-12

Oto inny sposób bez użycia calc().

// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
  margin: 0 2% 0 2%;
  width: 21%;
}

// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
  margin: 0 1.66666% 0 1.66666%;
  width: 30%;
}

// and so on!

To wszystko. Możesz uzyskać wymyślne wymiary, aby uzyskać bardziej estetyczne rozmiary, ale taki jest pomysł.


6
Nie testowałem tego, ale składnia CSS jest niepoprawna (wartości CSS nie są cytowane, a deklaracje powinny kończyć się średnikiem), więc na pewno nie będzie działać w obecnej formie.
— Nick F
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.