Skip to main content
CSS 5 mins read Devs2.org

CSS Box Model: Hiểu Từng Pixel Trong Layout Web

Khám phá chi tiết về CSS Box Model — content, padding, border, margin. Học cách tính kích thước phần tử, sử dụng box-sizing, và debug layout hiệu quả.

#CSS #Box Model #Web Development #Layout #Frontend #CSS Fundamentals

Minh họa CSS Box Model với 4 lớp content, padding, border, margin

Giới thiệu

Bạn đã bao giờ set width: 300px cho một phần tử, nhưng nó lại chiếm tới 350px trên màn hình? Hay bạn thấy hai phần tử cách nhau 50px dù bạn chỉ set margin 20px?

Nếu bạn từng gặp những tình huống này, chúc mừng — bạn đã chạm mặt với CSS Box Model, một trong những khái niệm quan trọng nhất (và cũng dễ gây nhầm lẫn nhất) trong CSS.

CSS Box Model là nền tảng của mọi layout web. Hiểu nó, bạn sẽ kiểm soát được từng pixel trong thiết kế của mình.

Box Model là gì?

Mỗi phần tử HTML trong CSS được biểu diễn dưới dạng một hình chữ nhật (box) gồm 4 lớp từ trong ra ngoài:

┌─────────────────────────────────┐
│            MARGIN               │
│  ┌───────────────────────────┐  │
│  │         BORDER            │  │
│  │  ┌─────────────────────┐  │  │
│  │  │      PADDING        │  │  │
│  │  │  ┌───────────────┐  │  │  │
│  │  │  │   CONTENT     │  │  │  │
│  │  │  │  (inner box)  │  │  │  │
│  │  │  └───────────────┘  │  │  │
│  │  └─────────────────────┘  │  │
│  └───────────────────────────┘  │
└─────────────────────────────────┘
  1. Content — Nội dung thực tế (text, image, video…)
  2. Padding — Khoảng đệm trong suốt quanh content
  3. Border — Đường viền bao quanh padding
  4. Margin — Khoảng cách trong suốt bên ngoài border

Từng lớp trong Box Model

1. Content

Đây là phần bên trong nhất — nơi chứa nội dung thực tế của phần tử. Kích thước của content được xác định bởi widthheight (hoặc tự động dựa vào nội dung).

.box {
  width: 300px;   /* Chiều rộng vùng content */
  height: 200px;  /* Chiều cao vùng content */
}

2. Padding

Padding là khoảng cách giữa content và border. Nó giúp “đệm” nội dung ra xa viền, tạo không gian thở cho phần tử.

.box {
  padding: 20px;              /* 20px cho cả 4 hướng */
  padding: 10px 20px;         /* trên/dưới: 10px, trái/phải: 20px */
  padding: 10px 15px 20px;    /* trên: 10px, trái/phải: 15px, dưới: 20px */
  padding: 10px 12px 14px 16px; /* trên, phải, dưới, trái (theo chiều kim đồng hồ) */
  
  /* Hoặc từng hướng riêng lẻ */
  padding-top: 10px;
  padding-right: 12px;
  padding-bottom: 14px;
  padding-left: 16px;
}

Lưu ý: Padding nằm bên trong background-color, có nghĩa là background của phần tử sẽ “trải dài” qua cả vùng padding.

3. Border

Border là đường viền bao quanh padding. Bạn có thể tùy chỉnh độ dày, kiểu dáng và màu sắc.

.box {
  border: 2px solid #3b82f6;  /* shorthand: độ dày, kiểu, màu */
  
  /* Hoặc từng thuộc tính riêng */
  border-width: 2px;
  border-style: solid;
  border-color: #3b82f6;
  
  /* Bo góc */
  border-radius: 8px;
  
  /* Từng cạnh riêng */
  border-top: 2px dashed #ef4444;
  border-bottom: 4px dotted #10b981;
}

Các kiểu border phổ biến:

  • solid — đường liền
  • dashed — đường đứt nét
  • dotted — đường chấm
  • double — đường đôi
  • none — không viền

4. Margin

Margin là khoảng cách bên ngoài border, tạo khoảng trống giữa phần tử này với phần tử khác.

.box {
  margin: 20px;               /* 20px cho cả 4 hướng */
  margin: 0 auto;             /* căn giữa ngang (khi có width xác định) */
  margin-top: 10px;
  margin-right: auto;         /* đẩy phần tử sang trái */
  margin-left: auto;          /* đẩy phần tử sang phải */
}

Mẹo: margin: 0 auto; là cách phổ biến nhất để căn giữa ngang một phần tử block có width xác định.

Cách tính kích thước — Content-box vs Border-box

Đây là phần quan trọng nhất của Box Model. Cách bạn tính kích thước phần tử phụ thuộc vào thuộc tính box-sizing.

Content-box (Mặc định)

Khi box-sizing: content-box (giá trị mặc định), widthheight chỉ áp dụng cho content — padding và border được cộng thêm vào kích thước tổng.

.box {
  box-sizing: content-box;
  width: 300px;
  padding: 20px;
  border: 2px solid #333;
}
/* Tổng chiều rộng thực tế: 300 + 20*2 + 2*2 = 344px */

Border-box (Khuyến nghị)

Khi box-sizing: border-box, widthheight bao gồm content + padding + border. Padding và border được “nén” vào bên trong kích thước đã định.

.box {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 2px solid #333;
}
/* Content width = 300 - 20*2 - 2*2 = 256px */
/* Tổng chiều rộng thực tế: 300px (đúng như mong đợi!) */

So sánh trực quan

Thuộc tínhcontent-boxborder-box
width = 300pxContent: 300pxContent: 256px (tự động tính)
padding: 20px+40pxNằm trong 300px
border: 2px+4pxNằm trong 300px
Tổng cộng344px300px

CSS Reset cho Border-box

Hầu hết các dự án hiện đại đều chuyển tất cả phần tử sang border-box bằng CSS reset:

*, *::before, *::after {
  box-sizing: border-box;
}

Đây là một trong những dòng code quan trọng nhất bạn có thể viết. Nó giúp việc tính toán layout trở nên trực quan và dễ dàng hơn rất nhiều.

Margin Collapsing

Margin collapsing là hiện tượng margin dọc (trên/dưới) của hai phần tử liền kề bị gộp lại thành một margin duy nhất.

Khi nào xảy ra?

  1. Phần tử anh em liền kề:
<div class="box-a">Box A</div>
<div class="box-b">Box B</div>
.box-a { margin-bottom: 30px; }
.box-b { margin-top: 20px; }
/* Khoảng cách thực tế: 30px (không phải 50px) */
  1. Phần tử cha và con đầu/cuối:
<div class="parent">
  <div class="child">Child</div>
</div>
.parent { background: #f0f0f0; }
.child { margin-top: 20px; }
/* Cả parent và child đều bị kéo xuống 20px */

Cách ngăn Margin Collapsing

  • Thêm border hoặc padding cho phần tử cha
  • Thêm overflow: hidden cho phần tử cha
  • Dùng display: flex hoặc display: grid trên phần tử cha
  • Dùng padding thay vì margin khi cần
/* Cách 1: Thêm padding nhỏ */
.parent { padding: 1px; }

/* Cách 2: overflow: hidden */
.parent { overflow: hidden; }

/* Cách 3: Flexbox (phổ biến nhất) */
.parent { display: flex; flex-direction: column; }

Box Model với các Display khác nhau

Block elements

.block {
  display: block;
  width: 200px;  /* Có hiệu lực */
  margin: 10px;  /* Có hiệu lực cả 4 hướng */
  padding: 10px; /* Có hiệu lực cả 4 hướng */
}

Inline elements

.inline {
  display: inline;
  width: 200px;   /* KHÔNG có hiệu lực! */
  height: 50px;   /* KHÔNG có hiệu lực! */
  margin-top: 10px;  /* KHÔNG có hiệu lực! */
  margin-bottom: 10px; /* KHÔNG có hiệu lực! */
  margin-left: 5px;   /* Có hiệu lực */
  margin-right: 5px;  /* Có hiệu lực */
  padding: 10px;   /* Có hiệu lực nhưng có thể tràn layout */
}

Inline-block elements

.inline-block {
  display: inline-block;
  width: 200px;   /* Có hiệu lực */
  height: 50px;   /* Có hiệu lực */
  margin: 10px;   /* Có hiệu lực cả 4 hướng */
  padding: 10px;  /* Có hiệu lực cả 4 hướng */
}
/* Hoạt động như inline nhưng vẫn giữ Box Model đầy đủ như block */

Debug Box Model với DevTools

Chrome DevTools là công cụ tốt nhất để debug Box Model:

  1. Inspect phần tử cần kiểm tra
  2. Vào tab Computed (bên phải)
  3. Kéo xuống phần Box Model — bạn sẽ thấy sơ đồ trực quan:
┌──────────────────────────────────┐
│ margin: 20px (orange)           │
│  ┌────────────────────────────┐  │
│  │ border: 2px (yellow)      │  │
│  │  ┌──────────────────────┐  │  │
│  │  │ padding: 15px (green)│  │  │
│  │  │  ┌────────────────┐  │  │  │
│  │  │  │ content: 268px │  │  │  │
│  │  │  │ (blue)         │  │  │  │
│  │  │  └────────────────┘  │  │  │
│  │  └──────────────────────┘  │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

Bạn cũng có thể hover vào phần tử trong Elements panel để thấy trực tiếp kích thước trên trang, hoặc click vào số dimension ở góc dưới bên phải màn hình DevTools.

Ví dụ thực tế

Ví dụ 1: Card Component

<div class="card">
  <h2>CSS Box Model</h2>
  <p>Hiểu Box Model để làm chủ layout.</p>
</div>
*, *::before, *::after {
  box-sizing: border-box;
}

.card {
  width: 320px;
  padding: 24px;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  margin: 20px auto;
  background: white;
  box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1);
}

.card h2 {
  margin: 0 0 8px 0;
  font-size: 1.5rem;
  color: #111827;
}

.card p {
  margin: 0;
  color: #6b7280;
  line-height: 1.6;
}

Kết quả: Card 320px (đúng như mong đợi nhờ border-box), nội dung cách viền 24px, có viền mỏng màu xám, bo góc 12px, và căn giữa trang.

Ví dụ 2: Navigation Bar

<nav class="nav">
  <a href="#" class="nav-link active">Home</a>
  <a href="#" class="nav-link">About</a>
  <a href="#" class="nav-link">Services</a>
  <a href="#" class="nav-link">Contact</a>
</nav>
.nav {
  background: #1e293b;
  padding: 12px 24px;
  display: flex;
  gap: 4px;
}

.nav-link {
  color: #cbd5e1;
  text-decoration: none;
  padding: 8px 16px;
  border-radius: 6px;
  transition: all 0.2s;
}

.nav-link:hover {
  background: #334155;
  color: white;
}

.nav-link.active {
  background: #3b82f6;
  color: white;
}

Ví dụ 3: Form Input với Icon

<div class="input-group">
  <span class="icon">🔍</span>
  <input type="text" placeholder="Search..." class="input">
</div>
.input-group {
  display: flex;
  align-items: center;
  border: 2px solid #d1d5db;
  border-radius: 8px;
  padding: 0 12px;
  width: 100%;
  max-width: 400px;
  box-sizing: border-box;
}

.input-group:focus-within {
  border-color: #3b82f6;
}

.icon {
  padding-right: 8px;
  font-size: 1.2rem;
}

.input {
  border: none;
  outline: none;
  padding: 12px 0;
  flex: 1;
  font-size: 1rem;
}

Những lỗi thường gặp với Box Model

Lỗi 1: Quên box-sizing

/* ❌ Sai */
.card {
  width: 100%;
  padding: 20px;
  border: 1px solid #ddd;
}
/* Tổng width real = 100% + 42px → tràn ngang */

/* ✅ Đúng */
*, *::before, *::after {
  box-sizing: border-box;
}
.card {
  width: 100%;
  padding: 20px;
  border: 1px solid #ddd;
}
/* Tổng width real = 100% */

Lỗi 2: Nhầm lẫn margin và padding

/* ❌ Dùng margin để tạo khoảng cách nội bộ */
.card {
  margin: 20px; /* Khoảng cách này ở bên ngoài */
  background: white;
}
/* Nội dung sát với viền, background không có padding */

/* ✅ Dùng padding cho khoảng cách nội bộ */
.card {
  padding: 20px; /* Khoảng cách bên trong */
  background: white;
}
/* Nội dung cách viền 20px, background trải đều */

Lỗi 3: Quên margin collapsing

/* ❌ Khoảng cách giữa các section không như mong đợi */
.section {
  margin-bottom: 40px;
}
.section:last-child {
  margin-bottom: 0; /* Bị vô hiệu bởi margin collapsing? */
}

/* ✅ Dùng padding hoặc gap (Flexbox) */
.container {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

Mẹo và best practices

  1. Luôn reset box-sizing ở đầu project:
*, *::before, *::after {
  box-sizing: border-box;
}
  1. Dùng padding cho khoảng cách nội bộ, margin cho khoảng cách giữa các phần tử

  2. Tránh margin dọc khi có thể — dùng gap (Flexbox/Grid) hoặc padding

  3. Debug bằng DevTools: Inspect → Computed → Box Model diagram

  4. Số đo trực quan: Khi dùng border-box, width: 100% luôn là 100% chính xác

  5. Dùng rem/em cho padding và margin để responsive dễ hơn:

.card {
  padding: 1.5rem; /* Tự động scale với font-size */
  margin-bottom: 1rem;
}
  1. Với layout phức tạp, ưu tiên Flexbox và Grid thay vì margin dồn dập

Kết luận

CSS Box Model là nền tảng của mọi layout web. Dù bạn làm việc với Flexbox, Grid, hay bất kỳ kỹ thuật layout nào, Box Model vẫn luôn hiện diện.

Ba điều cần nhớ:

  1. Luôn dùng border-box — reset ngay từ đầu project
  2. Phân biệt rõ content, padding, border, margin
  3. Debug bằng DevTools khi layout không như ý

Hiểu Box Model là bước đầu tiên để làm chủ CSS. Khi bạn nắm vững nó, mọi layout phức tạp đều trở nên đơn giản và dễ dự đoán.

Bài tập thực hành:

  1. Tạo một card component và thử thay đổi padding, border, margin để thấy sự khác biệt
  2. Chuyển từ content-box sang border-box và quan sát sự thay đổi
  3. Tạo layout 2 cột với margin dương và âm, xem margin collapsing hoạt động thế nào
  4. Dùng DevTools để inspect Box Model của một trang web bất kỳ

Recently Used Tools