CSS Box Model và box-sizing: border-box là gì vậy?


Lời đầu

Bài viết này là phần 2 trong series về box model. Bạn có thể theo dõi tất cả các phần tại đây.

Lý do chọn viết về CSS Box Model

Trong CSS và web layout, có rất nhiều kiến thức cơ bản mà lập trình viên giao diện cần nắm vững. Tuy nhiên, Box Model là một trong những khái niệm cơ bản mà lại vô cùng quan trọng trong việc xây dựng layout. Mình từng thấy các junior developer chỉ dùng kiểu “thử sai” trong việc layout, viết CSS dựa trên kinh nghiệm cá nhân hoặc chỉ để kết quả layout giống với design. Điều này có nhiều tác hại:

  • Bạn tự hình thành những kinh nghiệm sai và sẽ áp dụng chúng nhiều lần trong tương lai.
  • Có thể gặp lỗi layout tiềm ẩn và chỉ cần một sự thay đổi nhỏ là layout sẽ bị hỏng hoàn toàn. Bạn sẽ rất khó khăn trong việc sửa lỗi hoặc chỉ cố gắng lấp vá layout.
  • Mã code của bạn khó bảo trì sau này, đặc biệt khi có người mới tham gia vào dự án.
  • Mã code của bạn có thể được kiểm tra (nếu có) và sẽ được đánh giá kém nếu có một bên thứ ba xem xét.
  • Kiến thức không vững có thể dẫn đến những sai lầm trong buổi phỏng vấn.

Trong các bài sau, mình sẽ viết về các chủ đề cơ bản và quan trọng khác trong CSS như Inheritance, Cascade, Specificity, BFC, Flexbox, Grid…

Bài viết này dành cho ai?

Hãy tưởng tượng bạn tham gia một buổi phỏng vấn và được hỏi câu hỏi “Box model trong CSS là gì?”. Nếu bạn cảm thấy không tự tin trong việc trả lời câu hỏi này hoặc chỉ trả lời một cách ngắn gọn “nó nói về padding, margin, border của các element trên trang web”, thì bài viết này dành cho bạn.

Có Thể Bạn Quan Tâm :   Gonna, wanna, gimme… nghĩa là gì? Cách nói tắt trong tiếng Anh

Mình giả sử bạn đã có kiến thức cơ bản về CSS nên sẽ không giải thích chi tiết những phần ngoài phạm vi bài viết.

CSS Box Model là gì?

Điều quan trọng cần nhớ là mọi element trên trang web đều là các khối hình chữ nhật, bao gồm các hình tròn, hình oval hay đoạn văn bản dài hoặc ngắn:

Tất cả các element trên trang web đều là các khối hình chữ nhật.

Để giúp trình duyệt biết được chiều rộng/cao của một element và hiển thị chính xác theo ý của developer, box model là một công cụ mà trình duyệt dựa vào để tính toán. Box model trong CSS đơn giản là một tập quy tắc và công thức để trình duyệt xác định chiều rộng, chiều cao (và một số thông tin khác) của một element.

Các thành phần của Box Model

Như đã đề cập ở trên, mọi element là một khối hình chữ nhật và được chia thành 4 thành phần: content, padding, border, và margin (không nên việt hóa những từ này 😃). Mỗi thành phần có một đường biên tương ứng: content edge, padding edge, border edge, margin edge.

  • content: là phần chứa nội dung của một element, với chiều rộng/cao được xác định bằng thuộc tính width và height. Vùng này thường chứa text, hình ảnh, video…
  • padding: đại diện cho kích thước của vùng padding xung quanh phần content
  • border: đại diện cho kích thước (và kiểu dáng) của viền bao quanh vùng padding
  • margin: đại diện cho kích thước của vùng margin xung quanh vùng border

Đối với developer, bạn có thể dễ dàng xem các thuộc tính này của một element qua DevTools của trình duyệt.

Box model được minh họa trên DevTools của trình duyệt

Công thức tính mặc định:

  • Chiều rộng của một element = chiều rộng content + padding trái + padding phải + border trái + border phải
  • Chiều cao của một element = chiều cao content + padding trên + padding dưới + border trên + border dưới

Các thuộc tính 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ác thuộc tính cơ bản của box model

Chú ý rằng tôi không đưa ra margin trong công thức tính. Mặc dù margin là một phần của box model và liên quan đến element, nhưng nó không được tính vào chiều rộng/cao của element.

Có Thể Bạn Quan Tâm :   Stub, Mock và Fake trong unit test

Nếu bạn đã từng hỏi tôi về sự khác biệt giữa margin và padding. Tôi sẽ có một bài viết sau để giải thích chi tiết, nhưng đơn giản thì margin là vùng ở bên ngoài viền, còn padding là vùng bên trong viền. Việc chọn sử dụng margin hoặc padding là một điều cơ bản mà mọi developer cần hiểu rõ (bạn cũng có thể tìm hiểu thêm về sự khác biệt giữa hai thuộc tính này trên Google).

Quay trở về hiện tại

Vấn đề gây khó chịu 1:

Khi layout một trang web, có lúc bạn muốn thay đổi kích thước padding của một element hoặc thêm viền để nó trông đẹp hơn (theo thiết kế mới của designer chẳng hạn). Vấn đề là khi bạn thực hiện thay đổi đó, tổng chiều rộng của element sẽ thay đổi và làm thay đổi layout. Ví dụ:

Element (chiều rộng) = 200px (content) + 40px (padding) = 240px Khi bạn tăng giá trị padding lên 60px, chiều rộng của element sẽ tăng lên 260px và làm thay đổi layout. Để khắc phục vấn đề này, bạn phải giảm kích thước content xuống còn 180px để đảm bảo tổng chiều rộng vẫn là 240px. Hy vọng content co giãn tự động để tổng chiều rộng không thay đổi.

Thay đổi padding sẽ làm thay đổi layout như hình bên dưới:
Thay đổi padding làm thay đổi layout

Thay đổi viền cũng sẽ làm thay đổi layout như hình bên dưới:

Một vấn đề khó chịu khác là khi chiều rộng của một element con vượt ra ngoài phạm vi của cha

.parent {
  width: 300px;
  height: 300px;
  padding: 20px;
  border: 2px solid greenyellow;
}
.child {
  width: 300px;
  height: 200px;
  padding: 30px;
  color: #ffffff;
  background-color: steelblue;
}

Lỗi layout khi element con vượt ra ngoài phạm vi của cha

Giải pháp hiện tại

Box model đã được nâng cấp từ lâu với thuộc tính box-sizing và hai giá trị chính là content-box và border-box

  • content-box: mặc định, tất cả các element đều có giá trị content-box. Và đó là những gì đã được phân tích ở trên. Lưu ý rằng thuộc tính width và height chỉ định kích thước của content.
  • border-box: thuộc tính width và height sẽ tự động bao gồm cả content, padding và border. Ngoài ra, kích thước của content cũng sẽ tự động co giãn nếu chúng ta thay đổi kích thước của padding và border, đảm bảo kích thước của element không thay đổi và layout không bị thay đổi.
Có Thể Bạn Quan Tâm :   Phóng sự là gì?

Thực tế, rất hiếm khi có developer muốn quay trở lại quá khứ và sử dụng box-sizing với giá trị content-box trừ khi có những trường hợp đặc biệt trong dự án. (Hãy cho tôi biết nếu bạn có trường hợp nào cần sử dụng content-box)

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
  • Chiều cao của một element = height = chiều cao content (auto) + padding trên + padding dưới + border trên + border dưới

box-sizing: border-box giải quyết vấn đề layout rất tốt

Một trang web có hàng nghìn element, liệu việc thêm thuộc tính box-sizing vào từng element có khả thi không?

Tất nhiên là chúng ta sẽ không thêm box-sizing vào từng element một cách thủ công. Với sự trợ giúp của Universal selector *, chúng ta chỉ cần một dòng CSS đơn giản:

* {
  box-sizing: border-box;
}
/* Hoặc thận trọng hơn */
*, *::before, *::after {
  box-sizing: border-box;
}

Với đoạn code trên, tất cả các element sẽ có box-sizing là border-box, và bạn vẫn có thể ghi đè thuộc tính cho từng element cụ thể nếu cần.

.content-element {
  box-sizing: content-box;
}

Lưu ý

Để không làm cho bài viết cồng kềnh hơn, tôi đã cố gắng trình bày những trường hợp đơn giản và điển hình nhất và bỏ qua một số chi tiết khác. Ví dụ: Chiều rộng/cao của một element còn phụ thuộc vào nhiều yếu tố khác như min-width, max-width, min-height, max-height, hiệu ứng của flexbox…

Lời kết

Cảm ơn bạn đã đọc đến cuối bài viết. Hi vọng rằng bài viết đã giúp bạn hiểu thêm về CSS Box Model.

Box Model là một khái niệm cơ bản và được sử dụng hầu như mỗi ngày của mọi frontend developer. Vì vậy, nếu bạn chưa nắm vững nó, hãy dành thời gian để tìm hiểu thêm. Nếu bạn có bất kỳ phản hồi hoặc góp ý nào cho bài viết này, hãy để lại comment dưới đây.

Hãy tiếp tục theo dõi phần tiếp theo của series này: Phần 3: CSS Box Model – Các cách hiển thị element với thuộc tính display.

Back to top button