Nội dung bài viết được sự được cho phép của tác giả Lương Văn Phúc
Nội dung bài viết này là phần 2 của series về box model của mình. Chúng ta cũng có thể theo dõi phần 1 và phần 3 (cuối) tại:
Phần 1: CSS Box Model – Cơ bản dành cho những người mới mở màn
Phần 3: CSS Box Model – Những phương pháp hiển thị element với tính chất display
Lý do mình chọn viết về CSS Box Model
Trong thế giới của CSS hay web layout nói chung, có rất nhiều thứ cơ bản mà một lập trình viên giao diện cần nắm vững. Nhưng mình chọn Box Model để giới thiệu trước tiên vì nó rất cơ bản nhưng lại vô cùng quan trọng trong việc layout. Mình từng thấy các bạn junior khác chỉ layout kiểu ứng phó (thử sai), viết css theo bản năng hoặc kinh nghiệm member, miễn sao kết quả giống design hoặc chạy được là được.
Việc này còn có rất nhiều tác hại:
- Các các bạn sẽ tự hình thành các kinh nghiệm sai và sử dụng nhiều lần về sau.
- Sẽ có được những bug layout tiềm tàng và chỉ đợi 1 viên gạch bị vỡ, cả layout sẽ vỡ; các bạn sẽ loay hoay không biết nên fix từ đâu hoặc chỉ nỗ lực cố gắng tìm cách lấp vá layout.
- Code của các bạn sẽ rất khó maintain sau này, nhất là khi có người mới vào.
- Code của các bạn sẽ bị audit (nếu có) và được thẩm định kém nếu có một bên thứ 3 nhìn vào.
- Tri thức không vững cũng rất dễ bị vặn vẹo trong các buổi phỏng vấn.
Trong các bài tiếp theo, mình sẽ viết về những chủ đề cơ bản và cũng rất quan trọng khác của CSS như Inheritance, Cascade, Specificity, BFC, Flexbox, Grid…
Nội dung bài viết này giành cho ai?
Bạn hãy tưởng tượng mình đang tham gia một buổi phỏng vấn và được hỏi câu “Box model trong CSS là gì?”. Nếu khách hàng cảm giác không tự tín trả lời vướng mắc này, hoặc chỉ trả lời kiểu cụt ngủn “nó nói về padding, margin, border của mấy cái element trên website”, thì nội dung bài viết này là giành cho bạn.
Mình mặc định bạn đã sở hữu chút tri thức cơ bản về CSS nên sẽ không còn giảng giải rõ ràng những phần ngoài phạm vi nội dung bài viết.
CSS Box Model là gì?
Có một điều nếu như bạn luôn phải nhớ là bất kì element nào trên website đều là một khối hình chữ nhật, kể cả những hình tròn, hình oval, hay các đoạn text dài ngắn khác nhau:

Vậy để giúp browser biết được một element rộng/cao bao nhiêu để render cho xác thực và đúng ý của developer, box model là thứ mà browser dựa vào để tính toán. Nói lý thuyết hơn, box model trong CSS chỉ đơn giản là một tập các quy tắc và công thức cộng trừ để giúp browser xác định được chiều rộng, cao (và một số thứ khác) của một element.
Các thành phần của Box Model
Như mình san sẻ ở trên, bất kì element nào thì cũng là một khối hình chữ nhật, và nó gồm có 4 thành phần: content, padding, border, và margin (tốt nhất là không nên Việt hóa những từ này 😃 ). Mỗi thành phần đều phải sở hữu một đường biên giới phía bên ngoài tương ứng: content edge, padding edge, border edge, margin edge.
- content: là vùng chứa nội dung của một element, với chiều rộng/cao được xác định qua tính chất width và height. Vùng này thường chứa text, hình ảnh, video…
- padding: đã cho chúng ta thấy độ rộng của vùng padding xung quanh vùng content
- border: đã cho chúng ta thấy độ rộng (và style) của border xung quanh vùng padding
- margin: đã cho chúng ta thấy độ rộng của vùng margin xung quanh vùng border
Là một developer, bạn cũng có thể dễ dàng xem được những tính chất này của không ít element rất trực quan thông qua DevTools của browser.
Công thức tính đơn giản mặc định:
- Chiều rộng của một element = chiều rộng content width + padding trái + padding phải + border trái + border phải
- Độ cao của một element = độ cao content height + padding trên + padding dưới + border trên + border dưới
Các tính chất css tương ứng:
- Chiều rộng/cao của content: width, height
- Padding: padding, padding-left, padding-right, padding-top, padding-bottom
- Border: border, border-left, border-right, border-top, border-bottom
.element { width: 80px; height: 100px; padding: 30px 20px 40px; margin: 30px auto; border: 1px solid black; }

Có thể bạn để ý mình không liệt kê margin trong công thức. Mặc dù margin là một phần của box model và đi kèm với element, nhưng nó không được tính vào chiều rộng/cao của element.
Có bạn từng hỏi mình margin và padding khác nhau thế nào. Mình sẽ có được một nội dung bài viết phân biệt rõ ràng sau, nhưng nói đơn giản thì margin là vùng ở phía bên ngoài border, còn padding là vùng bên trong border, và khi nào dùng margin/padding cũng là một điều cơ bản mà các bạn developer cần nắm vững (bạn cũng có thể google để biết thêm về sự việc khác nhau giữa chúng).
Tất cả chỉ là quá khứ, hãy cùng quay về ngày nay:
Vấn đề từng gây khó chịu 1:
Khi layout một website, vững chắc sẽ có được những lúc bạn tăng giảm padding của một element, hay thêm border cho nó đẹp hơn (theo thiết kế mới của designer chẳng hạn). Vấn đề phát sinh là khi chúng ta thực hiện các thay đổi trên, tổng chiều rộng của element sẽ thay đổi và làm cả layout bị xê dịch vì những thay đổi đó.
Ví dụ cho dễ hiểu:
Element (chiều rộng) = 200px (content) + 40px (padding) = 240px
Khi chúng ta tăng padding lên 60px, chiều rộng của element sẽ tăng lên 260px, và sẽ đẩy những thứ xung quanh làm thay đổi layout. Để sửa lỗi này, bạn phải giảm chiều rộng của content còn 180px, để đảm bảo tổng chiều rộng vẫn là 240px. Giá như content nó tự giãn nở để đảm bảo tổng chiều rộng không đổi thì tốt biết mấy.


Vấn đề từng gây khó chịu 2:
Một lỗi layout thường gặp khác là chiều rộng của element con bị tràn thoát ra khỏi cha
.parent { width: 300px; height: 300px; padding: 20px; border: 2px solid greenyellow; } .child { width: 300px; height: 200px; padding: 30px; color: #ffffff; background-color: steelblue; }

Giải pháp ngày nay
Box model được nâng cấp (rất mất thời gian rồi) với tính chất box-sizing, 2 value đó là: content-box và border-box
- content-box: tất cả element đều được gán mặc định là content-box, và cũng là những gì mình phân tích ở trên. Lưu ý lại, tính chất width và height là để khái niệm chiều rộng/cao của phần content mà thôi nhé.
- border-box: tính chất width và height sẽ tự động hóa gồm có luôn content, padding và border, còn chiều rộng của content sẽ tự động hóa giãn nở tương ứng nếu tất cả chúng ta thay đổi padding và border, đảm bảo kích thước của tất cả element sẽ không còn thay đổi, đồng nghĩa với việc layout tổng sẽ không còn thay đổi.
Và khi box-sizing ra đời, “rất hiếm” developer nào (ý kiến member) muốn quay về quá khứ và sử dụng box-sizing với value là content-box nữa trừ những trường hợp đặc biệt quan trọng của project (Cho mình biết nếu như bạn có trường hợp nào cần dùng content-box nhé)
Công thức tính theo box-sizing: border-box:
- Chiều rộng của một element = width = chiều rộng content (auto) + padding trái + padding phải + border trái + border phải
- Độ cao của một element = height = độ cao content (auto) + padding trên + padding dưới + border trên + border dưới

Website có cả nghìn element, liệu việc thêm tính chất box-sizing vào từng element có khả thi?
Tất nhiên là tất cả chúng ta sẽ không còn phải thêm thủ công vào từng element, với sự viện trợ của Universal selector *, tất cả chúng ta chỉ việc một dòng CSS đơn giản:
* { box-sizing: border-box; } /* Hoặc cẩn thận hơn */ *, *::before, *::after { box-sizing: border-box; }
Với đoạn code trên, tất cả element sẽ tiến hành canh chỉnh và sửa chữa theo border-box, và đương nhiên bạn vẫn có thể dễ dàng override cho từng element cụ thể mà bạn muốn
.content-element { box-sizing: content-box; }
Lưu ý
Để không làm nội dung bài viết phức tạp hơn, mình nỗ lực cố gắng trình bày những trường hợp đơn giản và tiêu biểu nhất và bỏ qua một số rõ ràng khác. Ví dụ: Chiều rộng/cao của element còn bị ảnh hưởng tác động bởi nhiều yếu tố khác ví như min-width, max-width, min-height, max-height, các hiệu ứng của flexbox…
Lời kết
Cảm ơn bạn vì đã đọc đến tận cuối bài. Hi vọng nội dung bài viết đã bổ sung thêm phần nào tri thức về CSS Box model cho bạn.
Box model là nội dung khá cơ bản và được sử dụng hầu như mỗi ngày của bất kì frontend developer nào. Vì thế nếu như bạn chưa nắm vững nó thì hãy dành thời kì tìm hiểu thêm nhé.
Nội dung bài viết gốc được đăng tải tại grab-cv.com
Có thể bạn quan tâm:
- CSS Box Model – Cơ bản dành cho những người mới mở màn
- Xây dựng một bộ source SASS thế nào cho đẹp
- Căn giữa các thành phần HTML theo chiều dọc (phần 1)
Xem thêm các vị trí tuyển dụng it lương cao tại TopDev