Mẫu hộp

CSS Podcast – 001: Mô hình hộp

Giả sử bạn có đoạn mã HTML sau:

<p>I am a paragraph of text that has a few words in it.</p>

Sau đó, bạn viết CSS này cho nó:

p {
  width: 100px;
  height: 50px;
  padding: 20px;
  border: 1px solid;
}

Nội dung có chiều rộng 142 px, thay vì 100 px mà bạn chỉ định, và nội dung đó sẽ vượt ra ngoài phần tử của bạn. Tại sao lại như vậy?

Mô hình hộp là nền tảng cốt lõi của CSS. Việc hiểu cách hoạt động của mô hình hộp, cách mô hình này chịu ảnh hưởng của các khía cạnh khác của CSS và quan trọng là cách bạn có thể kiểm soát mô hình này có thể giúp bạn viết CSS dễ dự đoán hơn.

Việc tìm hiểu mô hình hộp của CSS sẽ giúp bạn biết được lý do nội dung không vừa với một phần tử.

Điều quan trọng cần nhớ là mọi thứ do CSS hiển thị đều là một hộp, ngay cả khi đó chỉ là một đoạn văn bản hoặc có một border-radius khiến nó trông giống như một hình tròn.

Nội dung và kích thước

Các hộp có hành vi khác nhau dựa trên giá trị display, kích thước đã đặt và nội dung mà chúng chứa. Nội dung này có thể là văn bản thuần tuý hoặc nhiều hộp hơn do các phần tử con tạo ra. Dù bằng cách nào, theo mặc định, nội dung sẽ ảnh hưởng đến kích thước của hộp.

Bạn có thể kiểm soát việc này bằng cách sử dụng định cỡ bên ngoài hoặc bạn có thể sử dụng định cỡ bên trong để cho phép trình duyệt đưa ra quyết định cho bạn dựa trên kích thước nội dung.

Sau đây là một bản minh hoạ cơ bản giải thích sự khác biệt:

Khi hộp có kích thước bên ngoài, sẽ có giới hạn về lượng nội dung bạn có thể thêm trước khi nội dung tràn ra ngoài hộp. Điều này khiến từ "awesome" tràn ra ngoài.

Bản minh hoạ có dòng chữ "CSS is awesome" (CSS thật tuyệt vời) trong một hộp có kích thước cố định và đường viền dày. Vì hộp có chiều rộng cụ thể nên hộp có kích thước bên ngoài. Điều này có nghĩa là nó kiểm soát việc định kích thước nội dung con. Tuy nhiên, từ "awesome" quá lớn so với hộp, nên từ này tràn ra ngoài border box (hộp đường viền) của hộp mẹ (sẽ nói thêm về vấn đề này sau). Một cách để ngăn tình trạng tràn này là cho phép hộp có kích thước vốn có bằng cách không đặt chiều rộng hoặc trong trường hợp này, hãy đặt width thành min-content. Từ khoá min-content yêu cầu hộp chỉ rộng bằng chiều rộng nội tại tối thiểu của nội dung (từ "tuyệt vời"). Nhờ đó, hộp sẽ vừa khít với văn bản.

Dưới đây là một ví dụ phức tạp hơn cho thấy tác động của các kích thước khác nhau đối với nội dung thực:

Định cỡ bên ngoài cho phép bạn kiểm soát kích thước của một phần tử. Kích thước nội tại giúp ngăn văn bản tràn.

Bật và tắt tính năng định cỡ nội tại để xem cách tính năng định cỡ bên ngoài giúp bạn kiểm soát tốt hơn bằng tính năng định cỡ bên ngoài và tính năng định cỡ nội tại giúp nội dung kiểm soát tốt hơn. Để xem hiệu ứng, hãy thêm một vài câu văn bản vào thẻ. Khi phần tử này có kích thước bên ngoài, sẽ có giới hạn về lượng nội dung bạn có thể thêm trước khi nội dung đó tràn, nhưng điều đó sẽ không xảy ra khi bạn bật kích thước bên trong.

Theo mặc định, phần tử này có một tập hợp widthheight gồm 400px mỗi loại. Các phương diện này đưa ra giới hạn nghiêm ngặt cho mọi thứ bên trong phần tử, được tuân thủ trừ phi nội dung quá lớn so với hộp. Bạn có thể thấy điều này trong thực tế bằng cách thay đổi chú thích bên dưới bức ảnh hoa thành một nội dung vượt quá chiều cao của hộp.

Thuật ngữ chính: Tràn nội dung xảy ra khi nội dung quá lớn so với hộp chứa nội dung đó. Bạn có thể quản lý cách một phần tử xử lý nội dung tràn bằng thuộc tính overflow.

Việc chuyển sang kích thước nội tại cho phép trình duyệt đưa ra quyết định cho bạn dựa trên kích thước nội dung của hộp. Điều này giúp giảm đáng kể khả năng xảy ra tình trạng tràn vì hộp sẽ đổi kích thước theo nội dung của nó.

Điều quan trọng cần nhớ là định cỡ nội tại là hành vi mặc định của trình duyệt và thường linh hoạt hơn nhiều so với định cỡ bên ngoài.

Các vùng của mô hình hộp

Các hộp được tạo thành từ các vùng mô hình hộp riêng biệt, tất cả đều thực hiện một công việc cụ thể.

Sơ đồ minh hoạ 4 khu vực chính của mô hình hộp – hộp nội dung, hộp phần đệm, hộp đường viền và hộp lề
Bốn khu vực chính của mô hình hộp: hộp nội dung, hộp phần đệm, hộp đường viền và hộp lề.

Hộp nội dung là vùng chứa nội dung. Nội dung có thể kiểm soát kích thước của thành phần mẹ, vì vậy, đây thường là khu vực có kích thước thay đổi nhiều nhất.

Padding box bao quanh content box và là khoảng trống do thuộc tính padding tạo ra. Vì khoảng đệm nằm bên trong hộp, nên nền của hộp sẽ xuất hiện trong khoảng trống mà khoảng đệm tạo ra. Nếu hộp có các quy tắc tràn được đặt, chẳng hạn như overflow: auto hoặc overflow: scroll, thì các thanh cuộn cũng chiếm không gian này.

Thanh cuộn nằm trong hộp khoảng đệm.

Hộp đường viền bao quanh hộp phần đệm và khoảng trống của hộp này được xác định bằng giá trị border. Giá trị này tạo ra một khung hình trực quan cho phần tử. Cạnh viền của phần tử là giới hạn của những gì bạn có thể thấy.

Khu vực cuối cùng, hộp lề, là khoảng trống xung quanh hộp, được xác định bằng quy tắc margin của hộp. Các thuộc tính như outlinebox-shadow cũng chiếm không gian này vì chúng được vẽ ở trên cùng của phần tử và không ảnh hưởng đến kích thước của hộp. Việc thay đổi outline-width của 200px trên một hộp sẽ không thay đổi bất cứ điều gì bên trong cạnh viền.

Đường viền rộng không ảnh hưởng đến kích thước của phần còn lại của phần tử.

Một ví dụ tương tự hữu ích

Mô hình hộp khá phức tạp để hiểu, vì vậy, sau đây là một ví dụ tương tự cho những gì bạn đã học được cho đến nay.

Ba khung ảnh.
Mô hình hộp minh hoạ bằng cách sử dụng khung hình ảnh thực.

Trong sơ đồ này, bạn có 3 khung ảnh được gắn cạnh nhau trên tường. Các phần tử của hình ảnh có khung tương ứng với mô hình hộp như sau:

  • Hộp nội dung là ảnh bìa.
  • Hộp đệm là tấm bìa cứng màu trắng, nằm giữa khung và tác phẩm nghệ thuật.
  • Hộp đường viền là khung, cung cấp đường viền theo nghĩa đen cho tác phẩm nghệ thuật.
  • Hộp lề là khoảng trống giữa các khung.
  • Bóng chiếm cùng không gian với hộp lề.

Gỡ lỗi mô hình hộp

Các công cụ dành cho nhà phát triển trên trình duyệt cung cấp hình ảnh minh hoạ về các phép tính mô hình hộp của một hộp đã chọn. Điều này có thể giúp bạn hiểu cách hoạt động của mô hình hộp và cách mô hình này ảnh hưởng đến trang web mà bạn đang làm việc.

Cách dùng thử tính năng này trong Chrome:

  1. Mở Công cụ cho nhà phát triển.
  2. Chọn một phần tử.
  3. Hiện trình gỡ lỗi mô hình hộp.
Trình gỡ lỗi mô hình hộp cho bản minh hoạ soutline.

Kiểm soát mô hình hộp

Để hiểu cách kiểm soát mô hình hộp, trước tiên, bạn cần hiểu những gì xảy ra trong trình duyệt.

Mọi trình duyệt đều áp dụng một biểu định kiểu tác nhân người dùng cho tài liệu HTML. Bảng định kiểu xác định giao diện và hành vi của các phần tử, nếu các phần tử không được cung cấp CSS xác định. CSS trong biểu định kiểu tác nhân người dùng sẽ thay đổi theo trình duyệt, nhưng mọi trình duyệt đều có các giá trị mặc định giúp nội dung dễ đọc hơn.

Biểu định kiểu của tác nhân người dùng đặt giá trị mặc định cho các phần tử lấy display. Ví dụ: giá trị display mặc định của phần tử <div>block, <li> có giá trị display mặc định là list-item<span> có giá trị display mặc định là inline.

Phần tử inline có khoảng lề khối, nhưng các phần tử khác không tuân theo khoảng lề này. Với inline-block, các phần tử khác sẽ tuân theo lề khối, nhưng phần tử đầu tiên vẫn giữ hầu hết các hành vi tương tự như khi là phần tử inline. Theo mặc định, một mục block sẽ lấp đầy khoảng trống nội tuyến có sẵn, trong khi các phần tử inlineinline-block chỉ lớn bằng nội dung của chúng.

Biểu định kiểu tác nhân người dùng cũng đặt giá trị mặc định cho box-sizing, cho biết một hộp cách tính kích thước của hộp đó. Theo mặc định, tất cả các phần tử đều được đặt thành box-sizing: content-box;. Điều này có nghĩa là khi bạn đặt các phương diện như widthheight, những phương diện đó sẽ áp dụng cho hộp nội dung. Nếu bạn đặt paddingborder, các giá trị này sẽ được thêm vào kích thước của hộp nội dung.

Kiểm tra mức độ hiểu biết của bạn

Kiểm tra kiến thức của bạn về các thuộc tính ảnh hưởng đến kích thước mô hình hộp.

.my-box {
  width: 200px;
  border: 10px solid;
  padding: 20px;
}

Bạn nghĩ .my-box sẽ rộng bao nhiêu?

200 px
Vì giá trị mặc định cho box-sizing là content-box, nên phần đệm và đường viền sẽ được thêm vào chiều rộng. 200px sẽ chính xác nếu hộp có box-sizing: border-box.
260px
Kích thước hộp mặc định là content-box, tức là phần đệm và đường viền được thêm vào hộp tổng thể.

Chiều rộng thực tế của hộp này là 260 px. Vì CSS sử dụng box-sizing: content-box mặc định, nên chiều rộng được áp dụng là chiều rộng của nội dung, đồng thời paddingborder ở cả hai bên sẽ được thêm vào chiều rộng đó. 200px cho nội dung + 40px cho khoảng đệm + 20px cho đường viền tạo thành tổng chiều rộng hiển thị là 260px.

Bạn có thể thay đổi kích thước này bằng cách chỉ định kích thước border-box:

.my-box {
  box-sizing: border-box;
    width: 200px;
    border: 10px solid;
    padding: 20px;
}

Mô hình hộp thay thế này yêu cầu CSS áp dụng width cho hộp đường viền thay vì hộp nội dung. Điều này có nghĩa là borderpadding của chúng ta sẽ được đẩy vào, vì vậy, khi bạn đặt .my-box thành chiều rộng 200px, thì trên thực tế, chiều rộng này sẽ hiển thị ở mức 200px.

Hãy xem cách hoạt động của tính năng này trong bản minh hoạ tương tác sau đây. Khi bạn bật/tắt giá trị box-sizing, vùng màu xanh dương sẽ cho biết CSS nào đang được áp dụng bên trong hộp.

So sánh hiệu ứng của việc định cỡ hộp nội dung và hộp đường viền.
*,
*::before,
*::after {
  box-sizing: border-box;
}

Quy tắc CSS này chọn mọi phần tử trong tài liệu và mọi phần tử giả ::before::after, đồng thời áp dụng box-sizing: border-box. Điều này có nghĩa là mọi phần tử hiện đều sử dụng mô hình hộp thay thế này.

Vì mô hình hộp thay thế có thể dễ dự đoán hơn, nên các nhà phát triển thường thêm quy tắc này vào các quy tắc đặt lại và chuẩn hoá, chẳng hạn như quy tắc này.

Tài nguyên

Biểu định kiểu tác nhân người dùng