- vừa được xem lúc

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

0 0 25

Người đăng: Văn Phúc

Theo Viblo Asia

Lời tựa

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

Phần 1: CSS Box Model - Cơ bản dành cho người mới bắt đầu
Phần 2: CSS Box Model và box-sizing: border-box là gì vậy?
Phần 3: CSS Box Model - Các cách hiển thị element với thuộc tính display

Các bạn theo dõi các bài blog cá nhân của mình tại đây nhé: GrabCV blog

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 đầu 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 đối phó (thử sai), viết css theo bản năng hoặc kinh nghiệm cá nhân, miễn sao kết quả giống design hoặc chạy được là được.

Việc này có rất nhiều tác hại:

  • 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ó những bug layout tiềm ẩn và chỉ đợi 1 viên gạch bị vỡ, cả layout sẽ vỡ; bạn sẽ loay hoay không biết nên fix từ đâu hoặc chỉ cố gắng tìm cách lấp vá layout.
  • Code của bạn sẽ rất khó maintain sau này, đặc biệt là khi có người mới vào.
  • Code của bạn sẽ bị audit (nếu có) và được đánh giá kém nếu có một bên thứ 3 nhìn vào.
  • Kiến 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…

Bài viết này dà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 bạn cảm giác không tự tin trả lời câu hỏi 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 trang web”, thì bài viết này là dành cho bạn.

Mình mặc định bạn đã có chút 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ì?

Có một điều nếu bạn luôn phải nhớ là bất kì element nào trên trang web đều là một khối hình chữ nhật, kể cả các 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 chính xá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 chia sẻ ở trên, bất kì element nào cũng là một khối hình chữ nhật, và nó bao gồm 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 có một đường biên 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 thuộc tính width và height. Vùng này thường chứa text, hình ảnh, video…
  • padding: cho biết độ rộng của vùng padding bao quanh vùng content
  • border: cho biết độ rộng (và style) của border bao quanh vùng padding
  • margin: cho biết độ rộng của vùng margin bao quanh vùng border

Là một developer, bạn có thể dễ dàng xem được các thuộc tính này của các 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
  • Chiều cao của một element = chiều cao content height + 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ó 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 marginpadding khác nhau thế nào. Mình sẽ có một bài viết phân biệt chi tiết sau, nhưng nói đơn giản thì margin là vùng ở 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ăn bản mà các bạn developer cần nắm vững (bạn có thể google để biết thêm về sự khác nhau giữa chúng).

Tất cả chỉ là quá khứ, hãy cùng quay về hiện tại:

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

Khi layout một trang web, chắc chắn sẽ 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 bạn 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 bạn 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ự co giãn để đảm bảo tổng chiều rộng không đổi thì tốt biết mấy.

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

Khi bạn thay đổi border, nó cũng sẽ làm thay đổi layout như hình bên dưới:

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 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 hiện tại

Box model được nâng cấp (rất lâu rồi) với thuộc tính box-sizing, 2 value chính là: content-boxborder-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, thuộc tính widthheight là để định nghĩa chiều rộng/cao của phần content mà thôi nhé.
  • border-box: thuộc tính widthheight sẽ tự động bao gồm luôn content, padding và border, còn chiều rộng của content sẽ tự động co giãn tương ứng nếu chúng ta thay đổi padding và border, đảm bảo kích thước của cả element sẽ không thay đổi, đồng nghĩa với việc layout tổng sẽ không thay đổi.

Và khi box-sizing ra đời, “rất hiếm” developer nào (quan điểm cá nhân) muốn quay lại 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 của project (Cho mình biết nếu 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
  • 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

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

Tất nhiên là chúng ta sẽ không phải thêm thủ công vào từng element, với sự 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 cẩn thận hơn */
*, *::before, *::after { box-sizing: border-box;
}

Với đoạn code trên, tất cả element sẽ được canh chỉnh 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 bài viết phức tạp hơn, mình 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 element còn bị ảnh hưởng bởi nhiều yếu tố khác 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 bài viết đã bổ sung thêm phần nào kiến 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 bạn chưa nắm vững nó thì hãy dành thời gian tìm hiểu thêm nhé. Nếu bạn có phản hồi hay góp ý gì cho bài viết thì hãy để lại comment bên dưới nhé.

Các bạn hãy nghiên cứu tiếp phần cuối cùng của serie này nhé:
Phần 3: CSS Box Model - Các cách hiển thị element với thuộc tính display

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 376

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 701

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 335

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 421

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414