Flexbox: 4 mặt hàng mỗi hàng


260

Tôi đang sử dụng hộp flex để hiển thị 8 mục sẽ tự động thay đổi kích thước với trang của tôi. Làm thế nào để tôi buộc nó chia các mục thành hai hàng? (4 mỗi hàng)?

Đây là một snip có liên quan:

(Hoặc nếu bạn thích 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
[Cập nhật] Câu hỏi này được dựa trên một thiết kế không phản hồi kém. Nếu bạn thấy mình sử dụng một trong những câu trả lời dưới đây, hãy cẩn thận. Trong một thiết kế tốt, bạn sẽ có nhiều mặt hàng hơn trên màn hình rộng hơn và ít hơn trên màn hình nhỏ hơn. Buộc 4 mục cho tất cả các kích thước màn hình sẽ chỉ trông hấp dẫn trên phạm vi hẹp của chiều rộng màn hình.
Vivek Maharajh

Câu trả lời:


381

Bạn đã có flex-wrap: wraptrên container. Điều đó tốt, bởi vì nó ghi đè giá trị mặc định, đó là nowrap( nguồn ). Đây là lý do các mặt hàng không bọc để tạo thành một lưới trong một số trường hợp .

Trong trường hợp này, vấn đề chính là flex-grow: 1về các mục flex.

Các flex-growtài sản không thực sự kích thước các mặt hàng flex. Nhiệm vụ của nó là phân phối không gian trống trong container ( nguồn ). Vì vậy, cho dù kích thước màn hình nhỏ đến mức nào, mỗi mục sẽ nhận được một phần tỷ lệ của không gian trống trên dòng.

Cụ thể hơn, có tám mục flex trong container của bạn. Với flex-grow: 1, mỗi người nhận được 1/8 không gian trống trên đường dây. Vì không có nội dung trong các mục của bạn, chúng có thể co lại thành chiều rộng bằng không và sẽ không bao giờ bao bọc.

Giải pháp là xác định chiều rộng trên các mục. Thử cái này:

.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>

Với flex-grow: 1định nghĩa trong tốc flexký, không cần phải flex-basiscó 25%, điều này thực sự sẽ dẫn đến ba mục mỗi hàng do lợi nhuận.

flex-growsẽ tiêu thụ không gian trống trên hàng, flex-basischỉ cần đủ lớn để thực thi một bọc. Trong trường hợp này, với flex-basis: 21%, có rất nhiều không gian cho lề, nhưng không bao giờ đủ không gian cho mục thứ năm.


1
Tôi thích điều này bởi vì nó hiệu quả với tôi, nhưng nhiều không gian, làm cho tôi cảm thấy hơi khó chịu. Có một số cửa sổ nhỏ hoặc tình huống mà ước tính này có thể làm tôi thất vọng?
Jackson

1
Những loại tình huống? Trong hầu hết các bố cục có những trường hợp cực đoan có thể tạo ra vấn đề. Những trường hợp như vậy thường đi qua các phân tích lợi ích chi phí bởi vì chúng không bao giờ, hoặc gần như không bao giờ xảy ra. Chẳng hạn, trong giải pháp trên, nếu bạn đặt lề rất lớn, bố cục có thể bị phá vỡ. Nếu đó là một vấn đề, thì nó nên được đăng trong câu hỏi. @Jackson
Michael Benjamin

2
Nếu bạn đặt ở mức lợi nhuận rất lớn, bố cục có thể phá vỡ Đây là một ví dụ về kịch bản tôi muốn tránh. Tôi không quan tâm đến thực tiễn; giải trí chầu của tôi cho sự hoàn hảo. Có cách nào để chính xác hơn?
Jackson

27
Bạn cũng có thể sử dụngflex: 1 0 calc(25% - 10px);
MarkG ngày

2
Câu trả lời chính xác! Một cải tiến nhỏ mà tôi sử dụng là margin: 2%;thay vì số pixel cố định để ngăn các hộp chuyển sang một dòng mới trên các thiết bị / độ phân giải nhỏ. công thức chung là (100 - (4 * box-width-percent)) / 8% cho các chiều rộng hộp khác nhau
thomaspsk

104

Thêm một chiều rộng cho các .childyếu tố. Cá nhân tôi sẽ sử dụng tỷ lệ phần trăm trên margin-leftnếu bạn muốn luôn có 4 phần trăm mỗi hàng.

BẢN GIỚI THIỆU

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

Ý tưởng tốt. Tôi đã sử dụng ý tưởng này với các chỉnh sửa nhỏ. jsfiddle.net/vivmaha/oq6prk1p/6
Vivek Maharajh

1
Ah. Điều này thực sự không giải quyết vấn đề của tôi. Xem ở đây để biết ví dụ: jsfiddle.net/vivmaha/oq6prk1p/7 . Tôi không có quyền tự do sử dụng tỷ lệ phần trăm cho khoản ký quỹ của mình. Chúng phải là một chiều rộng cố định. Điều này có nghĩa là 23% ma thuật mà chúng tôi đã chọn sẽ không hoạt động vì nó không tính đến tỷ lệ ký quỹ cố định.
Vivek Maharajh

3
Vâng, calc giải quyết nó! 'calc (100% * (1/4) - 10px - 1px)'. Xem jsfiddle.net/vivmaha/oq6prk1p/9
Vivek Maharajh

24
Vậy thì việc sử dụng flex trong này là gì?
hai lần vào

Điều gì về thiết kế đáp ứng? Chúng tôi không muốn đặt một chiều rộng cố định cho trẻ em
trò chơi nến

40

Đây là một apporach khác.

Bạn cũng có thể hoàn thành nó theo cách này:

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

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

Mẫu: https://codepen.io/caccoret/pen/WOPBBm

Và một mẫu hoàn chỉnh hơn: https://codepen.io/caccoret/pen/JyYaba


1
Nếu tôi có ít hơn 4 đứa con thì sao? Tôi không thích khoảng trống trống đó, đứa trẻ không phản ứng ...
xì phé

Câu trả lời khác của Muddasir Abbas chỉ sử dụng cài đặt flex, vì vậy tôi nghĩ đó là một giải pháp sạch hơn.
Andrew Koster

17

Tôi sẽ làm như thế này bằng cách sử dụng lề âm và calc cho máng xối:

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

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

Bản trình diễn: https://jsfiddle.net/9j2rvom4/


Phương pháp lưới CSS thay thế:

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

Bản trình diễn: 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>

Hy vọng nó giúp. để biết thêm chi tiết bạn có thể theo liên kết này


4

Tôi tin rằng ví dụ này là nhiều barebones và dễ hiểu hơn sau đó @dowomenfart.

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

Điều này thực hiện các tính toán chiều rộng tương tự trong khi cắt thẳng vào thịt. Toán học dễ dàng hơn và emtiêu chuẩn mới do khả năng mở rộng và thân thiện với thiết bị di động.


3
em không thực sự là tiêu chuẩn mới Nó có thể là một nỗi đau ở mông, và các nhà thiết kế không thiết kế với EM trong tâm trí.
Daniel 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
Nếu bạn có thể vui lòng thêm một số bối cảnh về lý do tại sao điều này trả lời câu hỏi OP thay vì chỉ đăng mã.
d219

nếu bạn thêm justify-content: space-evenly;vào prent, thì chúng sẽ được sắp xếp một cách độc đáo và bạn không cần phải làm điều đó calcvới đứa trẻ. Cảm ơn cho ví dụ, mặc dù!
Mattijs

0

Bọc Flex + lề âm

Tại sao flex so với display: inline-block?

Tại sao biên âm?

Hoặc bạn sử dụng SCSS hoặc CSS-in-JS cho các trường hợp cạnh (tức là phần tử đầu tiên trong cột) hoặc bạn đặt lề mặc định và loại bỏ lề ngoài sau.

Thực hiện

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

Đây là một cách khác mà không sử dụng 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!

Thats tất cả để có nó. Bạn có thể thích thú với các kích thước để có được kích thước thẩm mỹ hơn nhưng đây là ý tưởng.


6
Tôi đã không kiểm tra điều này, nhưng cú pháp CSS sai (giá trị CSS không được trích dẫn và các khai báo sẽ kết thúc bằng dấu chấm phẩy) để nó chắc chắn sẽ không hoạt động ở dạng hiện tại.
Nick F
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.