Podcast CSS – 010: Hộp linh hoạt
Một mẫu thiết kế có thể gặp khó khăn trong thiết kế thích ứng là thanh bên nằm cùng dòng với một số nội dung. Nếu có không gian khung nhìn, mẫu này hoạt động rất tốt, nhưng khi không gian được thu gọn, bố cục cứng nhắc đó có thể trở thành vấn đề.
Mô hình bố cục hộp linh hoạt (flexbox) là mô hình bố cục được thiết kế cho nội dung một chiều. Nó rất hiệu quả trong việc nhận hàng loạt mục có kích thước khác nhau và trả về bố cục tốt nhất cho các mục đó.
Đây là mô hình bố cục lý tưởng cho mẫu thanh bên này. Hộp linh hoạt không chỉ giúp sắp xếp thanh bên và nội dung cùng dòng, mà khi không có đủ không gian, thanh bên sẽ nằm sang một dòng mới. Thay vì đặt kích thước cứng nhắc để trình duyệt tuân theo, với flexbox, bạn có thể cung cấp các ranh giới linh hoạt để gợi ý cách hiển thị nội dung.
Bạn có thể làm gì với bố cục linh hoạt?
Bố cục linh hoạt có các tính năng sau đây mà bạn có thể khám phá trong hướng dẫn này.
- Các chỉ số này có thể hiển thị dưới dạng hàng hoặc cột.
- Chúng tuân theo chế độ viết của tài liệu.
- Theo mặc định, các giá trị này là một dòng, nhưng bạn có thể yêu cầu ngắt kết nối thành nhiều dòng.
- Các mục trong bố cục có thể được sắp xếp lại một cách trực quan, khác với thứ tự trong DOM.
- Không gian có thể được phân bổ bên trong các mục, vì vậy, chúng trở nên lớn hơn và nhỏ hơn theo không gian có sẵn trong thành phần mẹ.
- Bạn có thể phân bổ không gian xung quanh các mục và các đường linh hoạt trong một bố cục bao bọc, sử dụng thuộc tính Căn chỉnh hộp.
- Các mục có thể được căn chỉnh trên trục chéo.
Trục chính và trục chéo
Chìa khóa để tìm hiểu về flexbox là phải hiểu khái niệm trục chính và trục chéo.
Trục chính là trục do thuộc tính flex-direction
của bạn đặt.
Nếu đó là row
, trục chính của bạn nằm dọc theo hàng, còn nếu là column
, trục chính của bạn nằm dọc theo cột.
Các mục linh hoạt sẽ di chuyển theo nhóm trên trục chính. Hãy nhớ rằng: chúng tôi có rất nhiều thứ và đang cố gắng tạo bố cục tốt nhất cho chúng.
Trục chéo chạy theo hướng khác với trục chính. Vì vậy, nếu flex-direction
là row
thì trục chéo sẽ chạy dọc theo cột.
Bạn có thể làm hai việc trên trục chéo.
Bạn có thể di chuyển các mục riêng lẻ hoặc theo nhóm để chúng căn chỉnh với nhau và vùng chứa linh hoạt. Ngoài ra, nếu đã bao bọc các dòng linh hoạt, bạn có thể coi các dòng đó là một nhóm để kiểm soát cách chỉ định không gian cho các dòng đó.
Bạn sẽ thấy cách tất cả quy trình này hoạt động trong thực tế xuyên suốt hướng dẫn này. Giờ đây, hãy lưu ý rằng trục chính tuân theo flex-direction
.
Tạo vùng chứa linh hoạt
Hãy xem flexbox hoạt động như thế nào bằng cách lấy một nhóm các mục có kích thước khác nhau và sử dụng flexbox để bố trí các mục đó.
<div class="container" id="container">
<div>One</div>
<div>Item two</div>
<div>The item we will refer to as three</div>
</div>
Để sử dụng flexbox, bạn cần khai báo rằng bạn muốn sử dụng ngữ cảnh định dạng linh hoạt chứ không phải bố cục khối thông thường và bố cục cùng dòng.
Bạn có thể thực hiện việc này bằng cách thay đổi giá trị của thuộc tính display
thành flex
.
.container {
display: flex;
}
Như bạn đã tìm hiểu trong hướng dẫn về bố cục, thao tác này sẽ cung cấp cho bạn một hộp cấp khối, với các phần tử con của mục linh hoạt. Các mục linh hoạt ngay lập tức bắt đầu thể hiện một số hành vi flexbox, sử dụng giá trị ban đầu của chúng.
Các giá trị ban đầu có nghĩa là:
- Các mục sẽ hiển thị dưới dạng hàng.
- Không xuống dòng.
- Chúng không phát triển để lấp đầy vùng chứa.
- Chúng xếp hàng ở đầu vùng chứa.
Kiểm soát hướng của các mục
Mặc dù bạn chưa thêm thuộc tính flex-direction
, các mục sẽ hiển thị dưới dạng hàng vì giá trị ban đầu của flex-direction
là row
.
Nếu muốn thêm một hàng thì bạn không cần thêm thuộc tính.
Để thay đổi hướng, hãy thêm thuộc tính và một trong bốn giá trị:
row
: các mục được sắp xếp theo hàng.row-reverse:
các mục bố trí thành một hàng từ cuối vùng chứa linh hoạt.column
: các mục được bố trí dưới dạng cột.column-reverse
: các mục được bố trí dưới dạng cột từ cuối vùng chứa linh hoạt.
Bạn có thể thử tất cả các giá trị bằng cách sử dụng nhóm mặt hàng của chúng tôi trong bản minh hoạ bên dưới.
Đảo ngược luồng của mục và khả năng tiếp cận
Bạn nên thận trọng khi sử dụng bất kỳ thuộc tính nào sắp xếp lại màn hình hiển thị hình ảnh so với thứ tự của nội dung trong tài liệu HTML, vì điều này có thể ảnh hưởng tiêu cực đến khả năng tiếp cận.
Giá trị row-reverse
và column-reverse
là một ví dụ điển hình.
Việc sắp xếp lại chỉ diễn ra cho thứ tự hình ảnh, chứ không phải thứ tự logic.
Bạn cần phải hiểu điều này vì thứ tự logic là thứ tự mà trình đọc màn hình sẽ đọc to nội dung và bất kỳ ai sử dụng bàn phím cũng sẽ tuân theo.
Bạn có thể xem trong video sau đây về cách bố cục hàng đảo ngược, việc gắn thẻ giữa các đường liên kết bị ngắt kết nối khi điều hướng bằng bàn phím đi theo DOM chứ không phải màn hình hiển thị trực quan.
Bất cứ tác vụ nào có thể làm thay đổi thứ tự của các mục trong flexbox hoặc lưới đều có thể gây ra sự cố này. Do đó, trong quá trình sắp xếp lại trang web, bạn cần kiểm tra kỹ để đảm bảo trang web của bạn không gây khó khăn cho một số người khi sử dụng.
Để biết thêm thông tin, hãy xem:
Hướng và chế độ viết
Theo mặc định, các mục linh hoạt được sắp xếp theo hàng. Một hàng chạy theo hướng của các câu trong chế độ viết và hướng tập lệnh. Điều này có nghĩa là nếu bạn đang làm việc bằng tiếng Ả Rập, có hướng tập lệnh từ phải sang trái (rtl), các mục sẽ thẳng hàng ở bên phải. Thứ tự thẻ cũng sẽ bắt đầu ở bên phải vì đây là cách đọc các câu bằng tiếng Ả Rập.
Nếu bạn đang dùng chế độ viết dọc, chẳng hạn như một số kiểu chữ tiếng Nhật, thì một hàng sẽ chạy theo chiều dọc, từ trên xuống dưới.
Hãy thử thay đổi flex-direction
trong bản minh hoạ bằng cách sử dụng chế độ viết dọc.
Do đó, cách các mục linh hoạt hoạt động theo mặc định được liên kết với chế độ ghi của tài liệu. Hầu hết các hướng dẫn đều được viết bằng tiếng Anh hoặc một chế độ viết theo chiều ngang khác, từ trái sang phải. Điều này sẽ giúp bạn dễ dàng giả định rằng các mục linh hoạt nằm ở bên trái và chạy theo chiều ngang.
Với trục chính và trục chéo cùng với chế độ viết cần xem xét, việc chúng ta nói về start (bắt đầu) và end (kết thúc) thay vì trên, dưới, bên trái và bên phải trong hộp linh hoạt có thể sẽ dễ hiểu hơn. Mỗi trục có một điểm bắt đầu và một điểm kết thúc. Điểm bắt đầu của trục chính được gọi là điểm bắt đầu chính. Các mục linh hoạt ban đầu được sắp xếp từ đầu. Điểm cuối của trục đó là cuối cùng. Điểm bắt đầu của trục chéo là bắt đầu và điểm cuối giao diện.
Xuống dòng tự động
Giá trị ban đầu của thuộc tính flex-wrap
là nowrap
.
Điều này có nghĩa là nếu không có đủ không gian trong vùng chứa, các mục sẽ bị tràn.
Các mục hiển thị bằng giá trị ban đầu sẽ thu nhỏ hết mức có thể, xuống kích thước min-content
trước khi bị tràn.
Để khiến các mục bao bọc, hãy thêm flex-wrap: wrap
vào vùng chứa linh hoạt.
.container {
display: flex;
flex-wrap: wrap;
}
Khi một vùng chứa linh hoạt bao bọc, nó sẽ tạo ra nhiều đường linh hoạt. Về việc phân bổ không gian, mỗi dòng hoạt động như một vùng chứa linh hoạt mới. Do đó, nếu đang gói các hàng, thì bạn không thể lấy nội dung nào đó trong hàng 2 để khớp với nội dung nào đó phía trên hàng 1. Điều này có nghĩa là hộp linh hoạt là một chiều. Bạn có thể kiểm soát việc căn chỉnh trong một trục, một hàng hoặc một cột, chứ không phải cả hai cùng nhau như chúng ta có thể làm trong lưới.
Viết tắt của flex-flow
Bạn có thể đặt các thuộc tính flex-direction
và flex-wrap
bằng cách viết tắt flex-flow
.
Ví dụ: để đặt flex-direction
thành column
và cho phép các mục gói:
.container {
display: flex;
flex-flow: column wrap;
}
Kiểm soát không gian bên trong các mục linh hoạt
Giả sử vùng chứa của chúng ta có nhiều không gian hơn mức cần thiết để hiển thị các mục, thì các mục sẽ xếp hàng ngay từ đầu và không mở rộng để lấp đầy không gian.
Các quảng cáo này sẽ ngừng phát triển ở kích thước nội dung tối đa.
Điều này là do giá trị ban đầu của các thuộc tính flex-
là:
flex-grow: 0
: mục không tăng trưởng.flex-shrink: 1
: các mục có thể thu nhỏ nhỏ hơnflex-basis
.flex-basis: auto
: các mục có kích thước cơ sở làauto
.
Điều này có thể được biểu thị bằng giá trị từ khoá là flex: initial
.
Thuộc tính viết tắt flex
hoặc ký tự dài của flex-grow
, flex-shrink
và flex-basis
được áp dụng cho phần tử con của vùng chứa linh hoạt.
Để các mục tăng lên, đồng thời cho phép các mục lớn có nhiều không gian hơn các mục nhỏ sẽ sử dụng flex:auto
.
Bạn có thể thử điều này bằng cách sử dụng bản minh hoạ ở trên.
Thao tác này đặt các thuộc tính thành:
flex-grow: 1
: các mục có thể tăng lớn hơnflex-basis
của chúng.flex-shrink: 1
: các mục có thể thu nhỏ nhỏ hơnflex-basis
.flex-basis: auto
: các mục có kích thước cơ sở làauto
.
Việc sử dụng flex: auto
đồng nghĩa các mục sẽ có kích thước khác nhau vì không gian dùng chung giữa các mục sẽ được chia sẻ sau khi mỗi mục được bố trí ở kích thước nội dung tối đa.
Vì vậy, một mục lớn sẽ có nhiều không gian hơn.
Để buộc tất cả các mục có kích thước nhất quán và bỏ qua kích thước của nội dung, hãy thay đổi flex:auto
thành flex: 1
trong bản minh hoạ.
Thao tác này sẽ giải nén để:
flex-grow: 1
: các mục có thể tăng lớn hơnflex-basis
của chúng.flex-shrink: 1
: các mục có thể thu nhỏ nhỏ hơnflex-basis
.flex-basis: 0
: các mục có kích thước cơ sở là0
.
Việc sử dụng flex: 1
cho biết rằng tất cả các mục đều có kích thước bằng 0, do đó, toàn bộ không gian trong vùng chứa linh hoạt đều có sẵn để phân phối.
Vì tất cả các mục đều có hệ số flex-grow
là 1
, nên tất cả các mục đều tăng trưởng như nhau và không gian được chia sẻ đồng đều.
Cho phép các mục tăng trưởng ở tốc độ khác nhau
Bạn không cần phải cung cấp hệ số flex-grow
là 1
cho tất cả các mục.
Bạn có thể cung cấp hệ số flex-grow
khác nhau cho các mục linh hoạt.
Trong bản minh hoạ bên dưới mục đầu tiên có flex: 1
, flex: 2
thứ hai và flex: 3
thứ ba.
Khi các mục này tăng từ 0
, không gian có sẵn trong vùng chứa linh hoạt sẽ được chia sẻ thành 6.
Một phần được trao cho mục đầu tiên, 2 phần cho mục thứ hai và 3 phần cho mục thứ ba.
Bạn có thể thực hiện tương tự từ flex-basis
của auto
, mặc dù bạn cần chỉ định 3 giá trị.
Giá trị đầu tiên là flex-grow
, flex-shrink
thứ hai và flex-basis
thứ ba.
.item1 {
flex: 1 1 auto;
}
.item2 {
flex: 2 1 auto;
}
Đây là một trường hợp sử dụng ít phổ biến hơn vì lý do sử dụng flex-basis
của auto
là để cho phép trình duyệt tìm cách phân bổ không gian.
Nếu bạn muốn khiến một mục tăng trưởng hơn một chút so với mức thuật toán quyết định, nhưng điều này có thể sẽ hữu ích.
Sắp xếp lại các mục linh hoạt
Bạn có thể sắp xếp lại các mục trong vùng chứa linh hoạt bằng cách sử dụng thuộc tính order
.
Thuộc tính này cho phép sắp xếp các mục trong nhóm thứ tự.
Các mục được bố trí theo hướng do flex-direction
chỉ định, giá trị thấp nhất trước tiên.
Nếu nhiều mặt hàng có cùng giá trị thì mặt hàng này sẽ xuất hiện cùng với các mặt hàng khác có giá trị đó.
Ví dụ dưới đây minh hoạ thứ tự này.
Kiểm tra mức độ hiểu biết của bạn
Kiểm tra kiến thức của bạn về flexbox
Mặc định flex-direction
là
row
column
Theo mặc định, một vùng chứa linh hoạt sẽ gói phần tử con.
flex-wrap: wrap
với display: flex
để gói thành phần conMột mục con linh hoạt có vẻ như bị bóp méo, thuộc tính linh hoạt nào giúp giảm thiểu điều này?
flex-grow
flex-shrink
flex-basis
Tổng quan về căn chỉnh hộp linh hoạt
Hộp linh hoạt mang đến một tập hợp thuộc tính để căn chỉnh các mục và phân bổ không gian giữa các mục. Các thuộc tính này hữu ích đến mức đã được chuyển vào thông số kỹ thuật riêng, bạn cũng sẽ bắt gặp các thuộc tính này trong Bố cục lưới. Tại đây, bạn có thể tìm hiểu cách các chức năng này hoạt động khi bạn sử dụng flexbox.
Bạn có thể đặt tập hợp các cơ sở lưu trú thành hai nhóm. Thuộc tính phân phối không gian và thuộc tính căn chỉnh. Các cơ sở lưu trú phân phối không gian là:
justify-content
: phân bố không gian trên trục chính.align-content
: phân bố không gian trên trục chéo.place-content
: viết tắt để thiết lập cả hai thuộc tính trên.
Các thuộc tính dùng để căn chỉnh trong flexbox:
align-self
: căn chỉnh một mục duy nhất trên trục chéo.align-items
: căn chỉnh tất cả các mục dưới dạng một nhóm trên trục chéo.
Nếu bạn đang thao tác trên trục chính thì các thuộc tính sẽ bắt đầu bằng justify-
.
Trên trục chéo, chúng bắt đầu bằng align-
.
Phân bổ không gian trên trục chính
Với HTML được sử dụng trước đó, các mục linh hoạt được bố trí theo hàng, có không gian trên trục chính.
Các mục không đủ lớn để lấp đầy hoàn toàn vùng chứa linh hoạt.
Các mục xếp hàng ở đầu vùng chứa linh hoạt vì giá trị ban đầu của justify-content
là flex-start
.
Các mục được xếp hàng ở đầu và mọi khoảng trống thừa nằm ở cuối.
Thêm thuộc tính justify-content
vào vùng chứa linh hoạt, cung cấp giá trị flex-end
cho thuộc tính này, các mục sẽ sắp xếp ở cuối vùng chứa và không gian trống sẽ được đặt ở đầu.
.container {
display: flex;
justify-content: flex-end;
}
Bạn cũng có thể phân phối khoảng cách giữa các mục bằng justify-content: space-between
.
Hãy thử một số giá trị trong bản minh hoạ và xem MDN để biết tập hợp đầy đủ các giá trị có thể có.
Thông qua flex-direction: column
Nếu bạn đã thay đổi flex-direction
thành column
, thì justify-content
sẽ hoạt động trên cột này.
Để có không gian trống trong vùng chứa khi làm việc dưới dạng cột, bạn cần cung cấp cho vùng chứa height
hoặc block-size
.
Nếu không, bạn sẽ không có dung lượng trống để phân phối.
Hãy thử các giá trị khác, lần này là bố cục cột flexbox.
Phân bổ không gian giữa các đường linh hoạt
Với một vùng chứa linh hoạt được bao bọc, bạn có thể có không gian để phân phối trên trục chéo.
Trong trường hợp này, bạn có thể sử dụng thuộc tính align-content
có các giá trị giống với justify-content
.
Không giống như justify-content
(căn chỉnh các mục theo mặc định) cho flex-start
, giá trị ban đầu của align-content
là stretch
.
Thêm thuộc tính align-content
vào vùng chứa linh hoạt để thay đổi hành vi mặc định đó.
.container {
align-content: center;
}
Hãy thử tính năng này trong bản minh hoạ.
Ví dụ này có các dòng được bao bọc của các mục linh hoạt và vùng chứa có block-size
để chúng ta có một số không gian trống.
Viết tắt place-content
Để đặt cả justify-content
và align-content
, bạn có thể sử dụng place-content
với một hoặc hai giá trị.
Một giá trị duy nhất sẽ được dùng cho cả hai trục, nếu bạn chỉ định cả trục đầu tiên sẽ dùng cho align-content
và giá trị thứ hai cho justify-content
.
.container {
place-content: space-between;
/* sets both to space-between */
}
.container {
place-content: center flex-end;
/* wrapped lines on the cross axis are centered,
on the main axis items are aligned to the end of the flex container */
}
Căn chỉnh các mục trên trục chéo
Trên trục chéo, bạn cũng có thể căn chỉnh các mục trong đường linh hoạt bằng cách sử dụng align-items
và align-self
.
Không gian có sẵn cho cách căn chỉnh này sẽ phụ thuộc vào chiều cao của vùng chứa linh hoạt hoặc đường kẻ linh hoạt trong trường hợp một nhóm các mục được gói lại.
Giá trị ban đầu của align-self
là stretch
. Đó là lý do các mục linh hoạt trong một hàng kéo dài theo chiều cao của mục cao nhất theo mặc định.
Để thay đổi điều này, hãy thêm thuộc tính align-self
vào bất kỳ mục linh hoạt nào.
.container {
display: flex;
}
.item1 {
align-self: flex-start;
}
Sử dụng bất kỳ giá trị nào sau đây để căn chỉnh mục:
flex-start
flex-end
center
stretch
baseline
Xem danh sách đầy đủ các giá trị trên MDN.
Bản minh hoạ tiếp theo có một dòng mục linh hoạt với flex-direction: row
.
Mục cuối cùng xác định chiều cao của vùng chứa linh hoạt.
Mục đầu tiên chứa thuộc tính align-self
có giá trị flex-start
.
Hãy thử thay đổi giá trị trên thuộc tính đó để xem thuộc tính di chuyển như thế nào trong không gian của nó trên trục chéo.
Thuộc tính align-self
được áp dụng cho từng mục.
Bạn có thể áp dụng thuộc tính align-items
cho vùng chứa linh hoạt để đặt tất cả các thuộc tính align-self
riêng lẻ dưới dạng một nhóm.
.container {
display: flex;
align-items: flex-start;
}
Trong bản minh hoạ tiếp theo này, hãy thử thay đổi giá trị của align-items
để căn chỉnh tất cả các mục trên trục chéo dưới dạng một nhóm.
Tại sao không có phần tự biện minh trong flexbox?
Các mục linh hoạt hoạt động như một nhóm trên trục chính. Do đó, không có khái niệm tách một mục riêng lẻ ra khỏi nhóm đó.
Trong bố cục lưới, các thuộc tính justify-self
và justify-items
hoạt động trên trục cùng dòng để căn chỉnh các mục trên trục đó trong vùng lưới.
Do cách bố cục linh hoạt coi các mục là một nhóm, nên các thuộc tính này không được triển khai trong ngữ cảnh linh hoạt.
Bạn cần biết rằng flexbox hoạt động rất hiệu quả với lề tự động.
Nếu cần tách một mục khỏi một nhóm hoặc tách nhóm thành hai nhóm, bạn có thể áp dụng lề để làm việc này.
Trong ví dụ bên dưới, mục cuối cùng có lề trái là auto
.
Lề tự động sẽ hấp thụ tất cả không gian theo hướng được áp dụng.
Tức là thao tác này sẽ đẩy mục sang bên phải, do đó sẽ chia tách các nhóm.
Cách căn giữa một mục theo chiều dọc và chiều ngang
Bạn có thể sử dụng các thuộc tính căn chỉnh để căn giữa một mục bên trong một hộp khác.
Thuộc tính justify-content
căn chỉnh mục trên trục chính (là hàng). Thuộc tính align-items
trên trục chéo.
.container {
width: 400px;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
Kiểm tra mức độ hiểu biết của bạn
Kiểm tra kiến thức của bạn về flexbox
.container { display: flex; direction: ltr; }
Để căn chỉnh theo chiều dọc với flexbox, hãy sử dụng
.container { display: flex; direction: ltr; }
Để căn chỉnh theo chiều ngang với flexbox, sử dụng
.container { display: flex; direction: ltr; }
Theo mặc định, các mục linh hoạt sẽ được căn chỉnh theo stretch
. Nếu muốn sử dụng kích thước nội dung cho các mục con, bạn sẽ sử dụng kiểu nào sau đây?
justify-content: flex-start
align-content: start
content
sẽ căn chỉnh các đường linh hoạt, chứ không phải căn chỉnh mục con.height: auto
align-items: flex-start
Tài nguyên
- Bố cục hộp linh hoạt CSSN bao gồm một loạt hướng dẫn chi tiết kèm theo ví dụ.
- Hướng dẫn các mẹo CSS đối với Flexbox
- Điều gì sẽ xảy ra khi bạn tạo vùng chứa Flexbox Flex
- Mọi điều bạn cần biết về tính năng căn chỉnh trong Flexbox
- Hộp linh hoạt đó có kích thước lớn đến mức nào?
- Trường hợp sử dụng cho Flexbox
- Kiểm tra và gỡ lỗi bố cục Hộp linh hoạt của CSS trong Công cụ của Chrome cho nhà phát triển