Learn CSS Flexible Box Layout (Flexbox) in-depth, including axes, space distribution math (grow, shrink, basis), and alignment properties.

This lesson is currently only available in Vietnamese. Please switch the language toggle in the menu to Vietnamese to read the full guide and take the interactive quiz.

Trước khi CSS Flexible Box Layout (Flexbox) ra đời, dàn trang một chiều dọc hoặc ngang trên web là một cơn ác mộng của lập trình viên. Chúng ta phải lạm dụng float, display: inline-block hoặc các bảng HTML Table để căn chỉnh phần tử.

Flexbox ra đời như một mô hình bố cục hiện đại giúp tự động điều chỉnh kích thước phần tử để lấp đầy không gian chứa trống một cách thông minh, bất kể kích thước màn hình hiển thị.

1. Trục chính (Main Axis) & Trục phụ (Cross Axis)

Điểm mấu chốt để hiểu Flexbox là hệ tọa độ hai trục vuông góc:

  • Main Axis (Trục chính): Trục dọc theo đó các phần tử con được sắp xếp. Hướng của trục được xác định bởi thuộc tính flex-direction:
    • row (mặc định): Trục chính chạy nằm ngang từ trái sang phải.
    • column: Trục chính chạy thẳng đứng từ trên xuống dưới.
  • Cross Axis (Trục phụ): Trục vuông góc với trục chính. Hướng của trục phụ phụ thuộc hoàn toàn vào trục chính. Nếu trục chính là trục ngang, trục phụ sẽ là trục dọc và ngược lại.
ℹ️ Lưu ý: Khái niệm hướng viết (Writing Modes)
Main Axis và Cross Axis không cố định trái-sang-phải hay trên-xuống-dưới. Chúng phụ thuộc vào thuộc tính ngôn ngữ direction (như RTL của tiếng Ả Rập) và writing-mode. Flexbox hoạt động dựa trên các khái niệm trừu tượng: main-start, main-end, cross-start, và cross-end.

2. Sức mạnh tự co giãn: flex-grow, flex-shrink và flex-basis

Đây là ba thuộc tính áp dụng cho phần tử con (Flex Items) quyết định thuật toán phân bổ không gian của trình duyệt.

2.1 flex-basis (Kích thước gốc)

Độ rộng ban đầu của phần tử trước khi trình duyệt thực hiện phân chia không gian thừa hoặc co cụm. Có thể đặt theo pixel, phần trăm, hoặc dùng auto (mặc định - kích thước dựa theo nội dung của phần tử).

2.2 flex-grow (Hệ số giãn)

Khi tổng kích thước flex-basis của các con nhỏ hơn kích thước của container cha, chúng ta sẽ có không gian thừa (Remaining Space): $$\text{Remaining Space} = \text{Container Width} - \sum_{i} \text{flex-basis}_i$$ Các phần tử con có hệ số flex-grow > 0 sẽ chia nhau không gian thừa này theo tỷ lệ: $$\text{Allocated Space}_i = \text{Remaining Space} \times \frac{\text{flex-grow}_i}{\sum \text{flex-grow}}$$

flex-grow.css
.container {
  display: flex;
  width: 600px;
}
.item-1 {
  flex-basis: 100px;
  flex-grow: 1; /* Sẽ nhận 1/3 không gian thừa */
}
.item-2 {
  flex-basis: 200px;
  flex-grow: 2; /* Sẽ nhận 2/3 không gian thừa */
}
/* Tổng flex-basis = 300px. Không gian thừa = 600 - 300 = 300px.
   Item 1 nhận thêm: 300 * 1/3 = 100px -> Kích thước thực tế = 200px.
   Item 2 nhận thêm: 300 * 2/3 = 200px -> Kích thước thực tế = 400px. */

2.3 flex-shrink (Hệ số co)

Khi tổng kích thước flex-basis vượt quá kích thước container cha, chúng ta có không gian tràn (Overflow Space). Các con sẽ bị bóp nhỏ lại để vừa khít cha theo hệ số flex-shrink.

🔬 Đào sâu: Thuật toán co cụm của flex-shrink
Không giống như flex-grow phân chia đều theo hệ số, việc co cụm của flex-shrink tỷ lệ thuận với cả hệ số co và kích thước ban đầu (flex-basis) của phần tử để tránh việc phần tử nhỏ bị co quá đà gây biến dạng. $$\text{Scaled Shrink}_i = \text{flex-basis}_i \times \text{flex-shrink}_i$$ $$\text{Shrunk Space}_i = \text{Overflow Space} \times \frac{\text{Scaled Shrink}_i}{\sum \text{Scaled Shrink}}$$

Sân chơi tương tác: Flexbox Sandbox

Hãy trực tiếp điều chỉnh các thuộc tính của Flex Container và Flex Items bên dưới để xem trực quan thuật toán co giãn và căn lề hoạt động trong thời gian thực:

🎨 Sân chơi tương tác: Flexbox Sandbox

Container Controls

Item Configurator

1 w: auto
2 w: auto
3 w: auto
flexbox.html
<div class="container">
  <div class="item item-1">Item 1</div>
  <div class="item item-2">Item 2</div>
  <div class="item item-3">Item 3</div>
</div>
flexbox.css

3. Căn chỉnh và giãn cách: justify-content, align-items & gap

Một trong những ưu điểm lớn nhất của Flexbox là khả năng căn lề tự động mà không cần tính toán thủ công:

  • justify-content: Căn chỉnh các phần tử dọc theo trục chính (Main Axis). Gồm các giá trị: flex-start, flex-end, center, space-between (giãn cách đều, đẩy lề sát biên), space-around (khoảng cách biên bằng 1/2 khoảng cách giữa các phần tử), và space-evenly (mọi khoảng cách bằng nhau).
  • align-items: Căn chỉnh các phần tử dọc theo trục phụ (Cross Axis) cho toàn bộ container. Mặc định là stretch (tự động co kéo dài toàn phần để lấp đầy chiều cao dòng chứa).
  • align-self: Cho phép đè lên thuộc tính align-items chung tại riêng một phần tử con đặc thù.
  • gap: Thuộc tính cực kỳ hữu dụng để gán khoảng cách trống chính xác giữa các phần tử con mà không làm hỏng viền lề ngoài như khi sử dụng margin.
🕳️ Cạm bẫy: Cố gắng dùng justify-self
Trong Flexbox, thuộc tính justify-self không tồn tại và không có hiệu lực. Bạn chỉ có thể dùng align-self ở trục phụ. Ở trục chính, nếu muốn đẩy riêng một phần tử về một phía, hãy dùng kỹ thuật margin-left: auto hoặc margin-right: auto.

Trắc nghiệm ôn tập

Câu 1: Thuộc tính "justify-content" dùng để căn chỉnh các phần tử con dọc theo trục nào?

Trắc nghiệm ôn tập

Câu 2: Nếu có 3 phần tử con có flex-grow lần lượt là 0, 1, và 2. Trình duyệt chia không gian thừa như thế nào?

📖 Tài liệu tham khảo / References

Related Articles

Bài viết liên quan trong series

Lesson 3: CSS Grid — Two-Dimensional Layout Bài 3: CSS Grid 2 Chiều — Thiết Kế Bố Cục Phức Tạp Lesson 1: The Box Model & Flow Layout In-Depth Bài 1: Box Model Chuyên Sâu & Cơ Chế Dàn Trang Back to CSS Course Overview Quay lại Lộ trình Series CSS