Bạn có đang hiểu sai về position trong CSS (và cách sửa trong 10 phút)

Thuộc tính position trong CSS quyết định phần tử nằm ở đâu, chồng lên cái gì và phản ứng thế nào khi cuộn trang. Nghe thì đơn giản, nhưng chỉ cần trộn relative, absolute, fixed, sticky vào cùng một layout là rất dễ rơi vào trạng thái “sửa chỗ này vỡ chỗ kia”. Bài viết này giúp bạn nhìn lại toàn bộ hệ thống position bằng một demo trực quan, xây dựng bằng HTML/CSS/JS kết hợp UIkit, kèm mã nguồn đầy đủ để bạn tự tay thử nghiệm.

Bạn có đang hiểu sai về position trong CSS (và cách sửa trong 10 phút)

Demo trực quan: chọn mode position và xem phần tử thay đổi ra sao

Demo dưới đây mô phỏng một khối nội dung đơn giản. Bạn chỉ cần bấm nút để chuyển giữa các kiểu static, relative, absolute, xem phần tử di chuyển và chiếm chỗ trong layout như thế nào. Đồng thời còn có ví dụ về fixedsticky trong bối cảnh cuộn nội dung.

Chọn kiểu position

Bấm vào từng nút để xem cùng một phần tử phản ứng khác nhau với từng giá trịposition.

Nội dung nền (trong flow)
Hộp thử nghiệm
Mô tả sẽ hiển thị ở đây tùy theo mode bạn chọn.

Đây là ví dụ cực giản nhưng đủ để bạn cảm nhận: phần tử có nằm trong flow hay không, và nó bám theo hệ tọa độ của ai.

Cuộn để xem fixed và sticky

Ví dụ bên trái tập trung vào static/relative/absolute. Bên phải là vùng cuộn có header dùngsticky, và một nút dùngfixedbám theo cửa sổ trình duyệt.

Header sticky của vùng cuộn

Đoạn nội dung 1: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestias, voluptates.

Đoạn nội dung 2: Nulla facilisi. Proin feugiat tellus vitae urna pellentesque, at lacinia metus tincidunt.

Đoạn nội dung 3: Sed ac lectus sit amet libero rhoncus dictum eget non leo. Curabitur non mi in lacus placerat.

Đoạn nội dung 4: Suspendisse potenti. Integer volutpat, augue non luctus pellentesque, urna nibh commodo leo.

Đoạn nội dung 5: Nam pharetra lacinia risus, at eleifend leo ultrices ac. Suspendisse bibendum condimentum mi.

Đoạn nội dung 6: Phasellus eget maximus elit. Duis sit amet arcu ut arcu luctus efficitur.

Đoạn nội dung 7: Vivamus viverra, leo id bibendum accumsan, leo enim feugiat magna, vel pharetra neque turpis non arcu.

Khi bạn cuộn vùng này, phần header vẫn bám ở phía trên vùng cuộn vì đang dùngposition: sticky. Trong khi đó, nút “Trợ giúp” ở góc dưới màn hình làfixed, luôn đi theo viewport.

1. Position là gì và vì sao hay gây rối

Trong CSS, thuộc tính position trả lời ba câu hỏi:

  • Phần tử có còn tham gia vào flow bình thường của tài liệu hay không.
  • Nó được “neo” vào hệ tọa độ nào: chính nó, phần tử cha, hay viewport.
  • Những thuộc tính như top, right, bottom, left được hiểu theo cách nào.

Lý thuyết rất ngắn, nhưng khi áp dụng vào layout thực tế với nhiều phần tử lồng nhau, padding, margin, flex, grid… thì position trở thành điểm dễ sai. Nếu bạn đang phải dùng rất nhiều top/left “tạm bợ” để đẩy phần tử tới đúng chỗ, rất có thể gốc rễ là bạn đang hiểu sai hoặc lạm dụng position.

2. position: static – nền tảng của flow bình thường

static là giá trị mặc định của position. Khi một phần tử là static:

  • Nó nằm trong flow bình thường của layout, đẩy những phần tử khác ra trước sau.
  • Các thuộc tính top, left, right, bottom không có tác dụng.
  • Nó không tạo hệ tọa độ đặc biệt cho phần tử con.

Ví dụ:

<div class="block">Khối A</div>
<div class="block">Khối B</div>
.block {
  position: static; /* có thể bỏ vì đây là mặc định */
  padding: 12px;
  background: #f5f5f5;
  margin-bottom: 8px;
}

Nếu bạn chỉ cần layout theo chiều dọc hoặc chiều ngang, hãy ưu tiên flexbox và grid, không cần động tới position. Position chỉ nên xuất hiện khi bạn thật sự cần chồng lớp, neo góc, đè lên nhau hoặc bám theo viewport.

3. position: relative – dịch chuyển nhưng vẫn giữ chỗ

Khi chuyển một phần tử sang position: relative, bạn thay đổi hai điều:

  • Phần tử vẫn chiếm chỗ như cũ trong flow, nhưng có thể dịch chuyển bằng top, left, right, bottom.
  • Nó trở thành hệ tọa độ cho những phần tử con dùng position: absolute.

Đây là mô hình rất thường gặp khi cần gắn badge lên góc ảnh hoặc thẻ nội dung.

<div class="product-card uk-card uk-card-default uk-card-body">
  <span class="product-badge">-30%</span>
  <img src="image.jpg" alt="Sản phẩm" class="uk-margin-small-bottom">
  <h4 class="uk-margin-remove-bottom">Tên sản phẩm</h4>
</div>
.product-card {
  position: relative; /* tạo hệ tọa độ cho badge */
}

.product-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  background: #f0506e;
  color: #fff;
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 3px;
}

Nếu bỏ position: relative ở thẻ bao, badge rất dễ “trôi” tới một góc nào đó khó hiểu của giao diện. Khi debug layout có absolute, câu hỏi quan trọng nhất luôn là: phần tử này đang bám vào ai.

4. position: absolute – bám theo hệ tọa độ của ai?

Hiểu lầm phổ biến: absolute luôn bám theo toàn trang. Thực tế:

  • Nếu có một tổ tiên bất kỳ có position khác static thì phần tử absolute sẽ bám theo tổ tiên gần nhất đó.
  • Nếu không tìm được tổ tiên như vậy, nó mới bám theo viewport (hoặc root element).

Ví dụ minh họa với UIkit:

<div class="uk-card uk-card-default uk-card-body card-wrapper">
  <p>Nội dung chính của card</p>
  <button class="uk-button uk-button-primary card-button">
    Hành động
  </button>
</div>
.card-wrapper {
  position: relative; /* làm gốc tọa độ cho card-button */
  padding-bottom: 50px;
}

.card-button {
  position: absolute;
  bottom: 12px;
  right: 12px;
}

Khi card được lặp nhiều lần trong grid, mỗi nút sẽ bám đúng góc phải dưới của card tương ứng. Nếu bỏ position: relative ở wrapper, tất cả nút có thể chồng lên nhau ở một vị trí ngoài ý muốn.

5. position: fixed – bám theo cửa sổ trình duyệt

position: fixed được dùng khi bạn cần phần tử bám vào một vị trí cố định trên màn hình, không phụ thuộc vào phần tử cha và không bị ảnh hưởng khi cuộn nội dung bên trong một container nào đó. Các trường hợp điển hình:

  • Nút “lên đầu trang”.
  • Popup chat ở góc màn hình.
  • Thanh thông báo luôn hiện phía trên cùng.

Ví dụ đơn giản:

<button class="uk-button uk-button-primary back-to-top">
  Lên đầu trang
</button>
.back-to-top {
  position: fixed;
  right: 16px;
  bottom: 16px;
  border-radius: 999px;
}

Trong demo đầu bài viết, nút “Trợ giúp” hoạt động theo đúng cơ chế này: dù bạn cuộn vùng nội dung hay cuộn cả trang, nó vẫn bám ở góc dưới bên phải của cửa sổ trình duyệt.

6. position: sticky – trợ thủ tạo trải nghiệm đọc mượt mà

position: sticky là sự kết hợp giữa relativefixed. Ở trạng thái bình thường, phần tử cư xử như relative. Khi bạn cuộn tới một ngưỡng nhất định, nó “dính” lại như fixed nhưng chỉ trong phạm vi vùng cuộn.

Ví dụ một header trong vùng cuộn:

<div class="uk-card uk-card-default uk-card-body list-wrapper">
  <div class="list-heading">Bảng dữ liệu</div>
  <div class="list-body">
    <!-- nhiều dòng nội dung -->
  </div>
</div>
.list-wrapper {
  max-height: 300px;
  overflow-y: auto;
}

.list-heading {
  position: sticky;
  top: 0;
  background: #fff;
  padding: 8px 10px;
  border-bottom: 1px solid #eee;
}

Khi cuộn, header này sẽ bám ở phía trên vùng cuộn, giúp người dùng luôn nhìn thấy tiêu đề cột hoặc tên section mà vẫn không chiếm chỗ ở toàn bộ trang như fixed.

7. Những lỗi thường gặp khi dùng position

Đa số layout khó bảo trì đều bắt nguồn từ một vài sai lầm lặp đi lặp lại:

  • Dùng absolute để dựng cả layout: cố định từng phần tử bằng top/left trông có vẻ đúng ở một độ phân giải, nhưng chỉ cần nội dung dài hơn hoặc thiết bị khác là vỡ ngay.
  • Quên thiết lập phần tử cha làm gốc tọa độ: không đặt position: relative cho thẻ bao nhưng lại dùng absolute cho con, dẫn tới phần tử con bám vào một tổ tiên rất xa.
  • Nhầm lẫn giữa fixed và sticky: cần phần tử bám trong một khối nội dung cụ thể nhưng lại dùng fixed, khiến nó luôn đè lên mọi thứ khi người dùng cuộn qua các section khác.
  • Dùng position để “chữa cháy” thay vì thiết kế lại layout: thay vì cấu trúc lại bằng flex/grid, chỉ thêm absolute cho đến khi nhìn tạm ổn. Kết quả là CSS khó đọc, khó sửa, mỗi lần thêm nội dung là phải căn chỉnh lại từ đầu.

8. Chiến lược sử dụng position cho layout thực tế

Để layout vững và dễ bảo trì, có thể giữ một nguyên tắc đơn giản:

  • Dùng flexbox cho bố cục một chiều: hàng hoặc cột.
  • Dùng CSS grid cho bố cục hai chiều phức tạp.
  • Dùng margin, padding, gap cho khoảng cách.
  • Chỉ dùng position khi cần:
    • Chồng lớp: badge, tooltip, dropdown, overlay.
    • Bám viewport: nút, thanh điều hướng, popup.
    • Bám vùng cuộn: header bảng, sidebar filter, tiêu đề section.

Khi phải dùng position, hãy xác định rõ: phần tử này có cần giữ chỗ trong flow hay không, và nó cần bám vào hệ tọa độ nào. Trả lời được hai câu hỏi đó, bạn sẽ ít khi rơi vào vòng lặp thử từng giá trị position chỉ để “đến khi nào nó đúng thì thôi”.

9. Kết luận

Hiểu đúng về position là một bước quan trọng để nâng trình CSS. Chỉ với vài ví dụ nhỏ, bạn có thể thấy rõ sự khác biệt giữa static, relative, absolute, fixed và sticky trong cả layout đơn giản lẫn vùng cuộn phức tạp. Từ đó, mỗi khi cần đặt một phần tử vào vị trí “không bình thường”, bạn sẽ có lý do rõ ràng để chọn kiểu position phù hợp, thay vì chỉ thử tới khi ổn. Khi position không còn là vùng mù mờ, việc xây dựng giao diện ổn định và dễ mở rộng trở nên dễ dàng hơn rất nhiều.

Bình luận


  • Không có bình luận.

Công cụ trực tuyến

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...