Flexbox toàn tập
Bài viết này sẽ hướng dẫn cho bạn mọi thứ về flexbox, bao gồm tất cả các thuộc tính cho phần tử cha (flex container) và phần tử con (flex items).
Thuật ngữ
- Flex Layout: Flexible Box - vùng linh hoạt
- Flex container / Container: phần tử cha
- Flex items: phần tử con
- Components: các thành phần nhỏ của ứng dụng
Giới thiệu
Flex Layout (bắt đầu được đề xuất sử dụng bởi W3C từ tháng 10 năm 2017) nhằm cung cấp một phương thức dàn trang hiệu quả hơn cho việc bố trí, căn chỉnh và phân phối không gian giữa các flex items trong một container, ngay cả khi kích thước của chúng là động hoặc không xác định.
Ý tưởng chính phía sau của flex layout là cung cấp cho container khả năng thay đổi chiều rộng / chiều cao (và thứ tự) của các flex items nhằm lấp đầy không gian có sẵn một cách tốt nhất (chủ yếu là để phù hợp với tất cả các loại thiết bị và kích thước màn hình). Flex layout mở rộng các flex items để lấp đầy không gian trống có sẵn hoặc thu nhỏ chúng để chống tràn (overflow).
Quan trọng nhất, Flex layout được thực thi theo cách trái ngược với kiểu dàn trang truyền thống (theo từng block theo chiều dọc và inline theo chiều ngang). Mặc dù những thứ đó hoạt động tốt cho các trang, nhưng chúng thiếu tính linh hoạt để hỗ trợ các ứng dụng lớn hoặc phức tạp (đặc biệt khi nói đến thay đổi hướng, thay đổi kích thước, kéo dài, thu nhỏ, v.v.).
Lưu ý: Flex layout thích hợp nhất cho các components của ứng dụng hoặc các bố cục quy mô nhỏ (small-scale layouts), trong khi Grid layout dành cho bố cục quy mô lớn hơn (large-scale layouts).
Khái niệm cơ bản
Bởi flexbox là một bộ module chứ không phải một thuộc tính riêng lẻ, cho nên nó liên quan đến rất nhiều thứ bao gồm các bộ thuộc tính của nó. Một số thuộc tính được định nghĩa cho container (phần tử cha - parent element, hay vùng linh hoạt - flex container), trong khi một số thuộc tính khác được định nghĩa cho các phần tử con - flex items.
Nếu cách thức dàn trang thông thường đều dựa trên hướng block và inline thì flex layout được thiết kế dựa trên flex-flow
direction.
Các thành phần sẽ được sắp xếp theo trục chính - main axis (từ main-start tới main-end) hoặc theo trục chéo - cross axis (từ cross-start tới cross-end).
main-axis
: trục chính của một flex container là nơi mà các flex items được bố trí dọc theo đó. Hãy nhớ, nó không nhất thiết phải nằm ngang hay nằm dọc, nó hoàn toàn phụ thuộc vào thuộc tínhflex-direction
của container.main-start
|main-end
: các flex items đặt bên trong container được sắp xếp theo chiều ngang, bắt đầu từ main-start cho đến main-end.main-size
: kích thước chính của flex items. Nó có thể làwidth
- chiều rộng hoặcheight
- chiều cao, tùy thuộc vào trục chính - main axis của container.cross-axis
: trục chéo của một container. Nó nằm vuông góc với trục main-axis. Hướng của nó phụ thuộc vào hướng của main-axis.cross-start
|cross-end:
mang ý nghĩa tương tự với main-start và main-end, nhưng theo hướng vuông góc với chúng.cross-size
: kích thước của flex items. Nó có thể làwidth
- chiều rộng hoặcheight
- chiều cao, tùy thuộc vào trục chéo - cross axis của container.
Các thuộc tính dành cho parent - Container
display
Thuộc tính này giúp chỉ định một flex container. Các phần tử con trực tiếp của flex container sẽ trở thành flex items.
.container {
display: flex | inline-flex;
}
flex-direction
Thuộc tính này giúp chúng ta thiết lập main axis, từ đó xác định hướng hiển thị của các flex items bên trong container. Flexbox là một khái niệm bố cục đơn hướng (single-direction layout concept). Bạn hãy nhớ các flex items được bố trí chủ yếu theo hàng ngang hoặc dọc.
.container {
flex-direction: row | column | row-reverse | column-reverse;
}
row
(được thiết lập mặc định): chuyển trục main axis theo chiều ngang. Các flex items được hiển thị từ trái qua phải (ở chế độ ltr), và phải qua trái (ở chế độ rtl).row-reverse
: tương tự nhưrow
, nhưng đảo ngược thứ tự các flex items.column
: chuyển trục main axis theo chiều dọc. Các flex items được hiển thị từ trên xuống dưới (ở chế độ ltr), và từ dưới lên trên (ở chế độ rtl).column-reverse
: tương tự nhưcolumn
, nhưng đảo ngược thứ tự các flex items.
flex-wrap
Theo mặc định, trình duyệt sẽ cố gắng sắp xếp tất cả flex items trên cùng một hàng. Bạn có thể thay đổi nó và cho phép các flex items xuống dòng khi cần thiết với thuộc tính này.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap
(mặc định): tất cả flex items sẽ được xếp trên cùng một hàng.wrap
: các flex items sẽ được bọc trên nhiều dòng, từ trên xuống dưới.wrap-reverse
: tương tự vớiwrap
, nhưng theo thứ tự từ dưới lên trên.
Bạn có thể tham khảo một số ví dụ trực quan về flex-wrap
ở https://css-tricks.com/almanac/properties/f/flex-wrap/.
flex-flow
Đây là một cách viết tắt, giúp chúng ta chỉ định cả 2 thuộc tính flex-direction
và flex-wrap
. Giá trị mặc định của flex-flow
là row nowrap
.
.container {
flex-flow: column wrap;
}
justify-content
Thuộc tính này giúp xác định sự liên kết giữa các flex items dọc theo main axis. Nó giúp phân phối thêm không gian trống giữa các flex items trên cùng một hàng (flex line). Ngoài ra thuộc tính này còn thực hiện một số kiểm soát cho việc căn chỉnh các mục khi chúng tràn hàng (overflow).
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
flex-start
(được thiết lập mặc định): các flex items được sắp xếp về phía bắt đầu củaflex-direction
.flex-end
: các flex items được sắp xếp về nơi kết thúc củaflex-direction
.start
: các flex items được sắp xếp về phía bắt đầu của hướng ghi (writing-mode direction).end
: các flex items được sắp xếp về nơi kết thúc của hướng ghi (writing-mode direction).left
: các flex items được sắp xếp về phía bên trái của container, trừ khi nó không hợp lý với flex-direction thì nó sẽ hoạt động nhưstart
.right
: các flex items được sắp xếp về phía bên phải của container, trừ khi nó không hợp lý với flex-direction thì nó sẽ hoạt động nhưend
.center
: các flex items được căn giữa theo flex lines.space-between
: các mục được sắp xếp đều bên trong flex lines, các mục đầu tiên được xếp ở phần đầu của flex lines, các mục cuối cùng được sắp xếp tại phần cuối của flex lines.space-around
: các flex items được sắp xếp đều trên hàng với không gian bằng nhau giữa chúng. Cần lưu ý rằng, về mặt trực quan, trông có vẻ không gian giữa các mục là không đều nhau, điều này là do các flex items đều có cùng không gian trống ở hai bên.space-evenly
: các mục được phân phối khoảng trống là như nhau, kể cả khoảng cách giữa hai mục đầu và cuối so với container.
Bạn cũng cần lưu ý rằng, các trình duyệt khác nhau đều có một vài khác biệt nhất định cho các giá trị này. Ví dụ như space-between
hầu như chưa được hỗ trợ từ Edge, cũng như các giá trị left
| right
| start
| end
vẫn chưa có ở Chrome. Các giá trị an toàn nhất là flex-start
| flex-end
| center
.
Bạn có thể tham khảo liên kết sau để biết thêm chi tiết https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content.
Ngoài ra chúng ta còn có thêm một tham số bổ sung: safe
| unsafe
. Việc sử dụng safe
đảm bảo rằng cho dù bạn tùy chỉnh position như thế nào, bạn cũng không thể đẩy một phần tử ra bên ngoài màn hình theo cách nội dung đó không cuộn được (hay còn gọi là mất dữ liệu - data loss).
align-items
Giá trị này chỉ định behaviour mặc định của các flex items theo trục chéo trên flex line hiện tại. Bạn có thể nghĩ về nó như là một phiên bản justify-content
theo trục chéo cross axis.
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
stretch
: kéo dài chiều cao để lấp đầy container (tuy nhiên vẫn tuân theo min-width/max-width).flex-start
/start
: các flex items được sắp xếp về phía đầu trục chéo. Giá trịflex-start
áp dụng choflex-direction
trong khistart
áp dụng cho hướng ghi (writing-mode direction
).flex-end
/end
: các flex items được sắp xếp về phía cuối trục chéo. Giá trịflex-end
áp dụng choflex-direction
trong khiend
áp dụng cho hướng ghi (writing-mode direction
).center
: các flex items được căn giữa theo trục chéo.baseline
: các mục được căn chỉnh theo đường cơ sở.
Ngoài ra, tham số safe
| unsafe
có thể được sử dụng kèm theo để ngăn chặn việc căn chỉnh các phần tử khiến nội dung không truy cập được.
align-content
Thuộc tính này căn chỉnh các flex lines của container khi có khoảng trống bên trong trục chéo (cross axis), tương tự với cách mà justify-content
căn chỉnh các flex items theo trục chính (main axis).
Lưu ý: thuộc tính này sẽ vô hiệu khi container của bạn chỉ có duy nhất 1 flex line.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
flex-start
/start
: các flex items được sắp xếp về phía đầu của container. Giá trịflex-start
áp dụng choflex-direction
trong khistart
áp dụng cho hướng ghi (writing-mode direction
).flex-end
/end
: các flex items được sắp xếp về phía cuối của container. Giá trịflex-end
áp dụng choflex-direction
trong khiend
áp dụng cho hướng ghi (writing-mode direction
).center
: các flex items được phân phối vào chính giữa container.space-between
: các flex items được sắp xếp đồng đều, dòng đầu tiên ở sát phía đầu, dòng cuối cùng ở sát phía cuối.space-around
: các flex items được sắp xếp đồng đều với khoảng cách bằng nhau giữa mỗi flex line.space-evenly
: các flex items được phân phối đồng đều với khoảng cách bằng nhau giữa chúng.stretch
(default): các dòng được kéo dài độ cao nhằm chiếm hết không gian giữa chúng.
Các thuộc tính dành cho children - Flex Items
order
Theo mặc định, thứ tự các flex items trùng khớp với thứ tự của chúng trong mã HTML. Tuy nhiên, bạn có thể hoàn toàn tùy chỉnh thứ tự sắp xếp của chúng qua thuộc tính này.
.item {
order: 3; /* giá trị mặc định là 0 */
}
flex-grow
Thuộc tính này giúp xác định khả năng thay đổi kích thước của flex items khi cần thiết. Giá trị hợp lệ ở đây là một số nguyên đóng vai trò như tỉ lệ. Nó sẽ chỉ định lượng không gian mà các flex items có thể đạt đến bên trong container.
Khi tất cả các flex ỉtems được đặt flex-grow là 1, không gian bên trong container sẽ được chia đều cho toàn bộ chúng. Nếu một vài flex item có giá trị bằng 2, thì kích thước của chúng sẽ gấp đôi so với các flex items còn lại (điều này không hoàn toàn đúng nhưng ít nhất hệ thống sẽ cố gắng để đạt được điều đó).
flex-grow
được sử dụng khi tổng kích thước các flex items bên trong container của bạn nhỏ hơn kích thước của container, và bạn muốn nội dung bên trong container được lấp đầy.
.item {
flex-grow: 1; /* giá trị mặc định là 0 */
}
Giá trị nhỏ hơn 0 là không hợp lệ.
flex-shrink
Thuộc tính này chỉ định khả năng thu nhỏ kích thước của flex items khi cần thiết.
Ngược lại so với flex-grow
, flex-shrink
được sử dụng khi tổng kích thước các flex items lớn hơn kích thước của container, và bạn muốn các flex items co lại cho phù hợp với container.
.item {
flex-shrink: 2; /* giá trị mặc định là 0 */
}
Giá trị nhỏ hơn 0 là không hợp lệ.
flex-basis
Thuộc tính này xác định kích thước mặc định của một phần tử trước khi không gian còn lại được phân phối. Các giá trị hợp lệ bao gồm:
number
: một đơn vị đo lường xác định (20%, 5rem, 100px...).auto
: mang ý nghĩa hệ thống sẽ tự động xem xét kích thước (width
/height
) của flex items (điều này được thực hiện tạm thời cho tới khi không cần nữa).
.item {
flex-basis: 100px | 20% | 100rem | ... | auto; /* giá trị mặc định là auto */
}
Nếu giá trị được thiết lập về 0, không gian thừa xung quanh nội dung sẽ không được tính vào. Nếu giá trị được thiết lập thành auto
, không gian thừa sẽ được phân phối dựa trên giá trị flex-grow
của chúng.
flex
Đây là cách viết tắt để thiết lập cả 3 thuộc tính flex-grow
, flex-shrink
, và flex-basis
. Tham số thứ hai (flex-shrink
) và thứ ba (flex-basis
) là không bắt buộc.
.item {
flex: 1; /* flex-grow = 1, flex-shrink = 1, flex-basis = 0 */
flex: 1 1 0;
}
Giá trị mặc định của thuộc tính này là 0 1 auto.
Thuộc tính này được khuyên dùng hơn là việc thiết lập các thuộc tính con một cách riêng lẻ.
align-self
Bạn có thể hiểu thuộc tính này giống như align-items
, nhưng chỉ tác dụng cho một số flex items riêng lẻ.
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
Lưu ý rằng các thuộc tính như float
, clear
, vertical-align
sẽ không có tác dụng đối với các flex items.
Kết luận
Bài viết tới đây là kết thúc rồi. Cá nhân mình cảm nhận flexbox cực kỳ hay và hiệu quả cho việc dàn trang, nhất là với các trang có hỗ trợ mobile view.
Hi vọng thông qua bài viết này, các bạn sẽ nắm vững kiến thức về flexbox hơn. Nếu có câu hỏi gì thì các bạn cứ liên hệ với mình nhé.