Bốn lớp của mọi hộp
Mọi phần tử trên trang được vẽ thành một hình chữ nhật gồm bốn lớp, từ trong ra ngoài:
- Content: chữ, ảnh hoặc các phần tử con, có kích thước theo
widthvàheight. - Padding: khoảng trống bên trong hộp, giữa nội dung và đường viền. Vùng này hiện nền của phần tử.
- Border: đường viền bao quanh padding.
- Margin: khoảng trống bên ngoài đường viền, đẩy các hộp khác ra xa. Luôn trong suốt.
Trong ví dụ, mỗi lớp có màu riêng: nội dung màu xanh dương, padding màu xanh lá, đường viền tối màu, và vùng màu hổ phách quanh hộp chính là margin (được vẽ bằng một phần tử bọc, vì bản thân margin trong suốt).
Dòng bên dưới hộp do trình duyệt đo: 160 + 20 + 20 + 10 + 10 = 220px. Margin còn thêm 24px mỗi bên, nhưng nó nằm ngoài hộp nên không thuộc con số 220.
Cách tính chiều rộng: content-box và border-box
Theo mặc định (box-sizing: content-box), width chỉ đặt kích thước cho nội dung. Padding và border được cộng thêm bên ngoài, nên hộp cuối cùng rộng hơn con số bạn viết. Với box-sizing: border-box, width là toàn bộ hộp, và nội dung co lại để nhường chỗ cho padding và border.
content-box (mặc định) | border-box | |
|---|---|---|
width nghĩa là | Nội dung | Nội dung + padding + border |
width: 200px; padding: 20px; border: 5px | Rộng 250px | Rộng 200px |
| Vùng nội dung trong trường hợp đó | 200px | 150px |
| Margin | Bên ngoài, không tính | Bên ngoài, không tính |
Đoạn reset border-box
Vì border-box giúp kích thước cộng lại hợp lý, hầu hết stylesheet hiện đại đều bắt đầu bằng quy tắc này:
*,
*::before,
*::after {
box-sizing: border-box;
}
Điều này quan trọng nhất khi dùng phần trăm. Hai cột width: 50% có padding sẽ không vừa trên một dòng với content-box, vì mỗi cột là 50% cộng thêm padding:
(Các chú thích HTML xóa khoảng trắng giữa hai cột inline-block, nếu không nó sẽ cộng thêm vài pixel.)
Xem box model trong DevTools
Trình duyệt nào cũng vẽ sẵn box model cho bạn. Nhấp chuột phải vào một phần tử, chọn Inspect và mở tab Computed (Layout trong Firefox): một sơ đồ hiện kích thước nội dung ở giữa, bao quanh là các giá trị padding, border và margin. Di chuột lên một phần tử trong bảng Elements cũng tô màu trang: nội dung xanh dương, padding xanh lá, margin cam.
Hộp inline theo quy tắc khác
Box model ở trên mô tả các hộp block như <div> và <p>. Phần tử inline như <span>, <a> và <strong> nằm gọn trong một dòng chữ, và xử lý khoảng trống theo chiều dọc khác hẳn:
| Thuộc tính | Trên phần tử inline |
|---|---|
width, height | Bị bỏ qua |
| Padding, border, margin theo chiều ngang | Được áp dụng, và đẩy phần tử bên cạnh sang ngang |
| Padding và border theo chiều dọc | Được vẽ, nhưng không đẩy các dòng phía trên và phía dưới |
| Margin theo chiều dọc | Bị bỏ qua |
display: inline-block cho phần tử nằm trong dòng chữ đầy đủ box model: width, height, padding và margin đều chiếm chỗ. Xem chi tiết từng lớp ở padding trong CSS và margin trong CSS.
Lỗi thường gặp
- Thêm padding cho hộp có chiều rộng cố định rồi thắc mắc vì sao nó to ra. Với
content-box, padding và border được cộng vàowidth. Hãy dùngborder-box. - Mong margin có màu nền. Margin luôn trong suốt; dùng padding nếu cần khoảng trống có màu.
- Đặt
heighthoặc margin dọc cho phần tử inline. Không có gì xảy ra; hãy dùngdisplay: inline-blockhoặcblock. - Quên tính border. Viền 1px trên phần tử
width: 100%làm nó rộng thừa 2px vớicontent-box, có thể sinh ra thanh cuộn ngang. - Nhầm margin với padding. Nói ngắn gọn: padding ở bên trong đường viền, margin ở bên ngoài. Trang margin và padding đặt hai thuộc tính cạnh nhau để so sánh.
Câu hỏi thường gặp
Box model trong CSS là gì?
Là quy tắc mà theo đó mọi phần tử được hiển thị thành một hộp chữ nhật gồm bốn lớp: nội dung (content), phần đệm (padding) bao quanh nó, đường viền (border) bao quanh padding, và lề (margin) bên ngoài đường viền. Chiều rộng, chiều cao và khoảng cách trong CSS đều được đặt trên các lớp này.
box-sizing: border-box có tác dụng gì?
Nó khiến width và height bao gồm cả padding và border. Một hộp width: 200px có padding: 20px và viền 5px khi đó rộng đúng 200px, và vùng nội dung co lại còn 150px cho vừa. Giá trị mặc định, content-box, cộng thêm padding và border bên ngoài, thành 250px.
Tổng chiều rộng của một phần tử được tính thế nào?
Với content-box mặc định: width + padding trái và phải + border trái và phải. Với border-box: chỉ là width. Trong cả hai trường hợp, margin nằm ngoài hộp, nên nó cộng vào khoảng không gian phần tử chiếm chứ không cộng vào chiều rộng của chính phần tử.
Margin có thuộc box model không?
Có, đó là lớp ngoài cùng, nhưng nó luôn trong suốt và không bao giờ được tính vào chiều rộng hay nền của chính phần tử. Nó chỉ đẩy các hộp bên cạnh ra xa.
Có nên đặt box-sizing: border-box cho mọi thứ không?
Phần lớn dự án làm vậy, với *, *::before, *::after { box-sizing: border-box; } ở đầu stylesheet. Cách này giúp chiều rộng phần trăm và padding cộng lại đúng như người ta mong đợi, và các framework như Bootstrap và Tailwind cũng kèm sẵn đoạn reset này.