Bài 11. Định vị: position, z-index, float

Thuộc tính position cho phép đặt phần tử ở vị trí chính xác: dịch khỏi chỗ cũ, ghim theo khung nhìn, dính khi cuộn hay đè lên phần tử khác. Bài này giải thích năm giá trị position, hệ quy chiếu, z-index, ngữ cảnh xếp lớp và float.

50 phútTrung cấp
Bạn sẽ học được
  • Phân biệt static, relative, absolute, fixed, sticky
  • Hiểu “phần tử cha định vị” làm mốc cho absolute
  • Dùng top/right/bottom/left và inset
  • Điều khiển xếp lớp với z-index; biết float/clear
Thuật ngữ cần biết
Containing block
Khung tham chiếu để tính top/left.
Stacking context
Nhóm xếp lớp; z-index chỉ so sánh trong cùng nhóm.
Sticky
Bình thường như relative, dính lại khi cuộn tới ngưỡng.

Một số khái niệm

positionChiếm chỗ cũMốc tọa độDùng cho
static (mặc định)CóKhông áp dụng top/leftBình thường
relativeCóChính vị trí cũDịch nhẹ; làm mốc cho con absolute
absoluteKhôngTổ tiên gần nhất có position khác staticNhãn, nút đóng, chú thích đè ảnh
fixedKhôngKhung nhìn (viewport)Thanh menu, nút lên đầu trang
stickyCóKhung cuộn gần nhấtTiêu đề bảng, mục lục dính

Mẹo kinh điển: đặt position: relative cho cha và position: absolute cho con, khi đó top/right của con tính theo cha.

relative + absolute

<style>
  .the { position: relative; width: 260px; height: 140px; border-radius: 12px; background: url("https://picsum.photos/seed/mocchau/520/280") center/cover; }
  .nhan { position: absolute; top: 10px; left: 10px; background: #e53935; color: #fff; font-size: 12px; padding: 2px 8px; border-radius: 10px; }
  .dong { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 50%; border: 0; background: rgb(0 0 0 / .5); color: #fff; }
  .chu { position: absolute; inset: auto 0 0 0; padding: 8px 12px; color: #fff; background: linear-gradient(transparent, rgb(0 0 0 / .7)); border-radius: 0 0 12px 12px; }
</style>
<div class="the"><span class="nhan">Giảm 20%</span><button class="dong">×</button><div class="chu">Mộc Châu mùa hoa mận</div></div>
Kết quả hiển thị

sticky và fixed

<style>
  .cuon { height: 170px; overflow: auto; border: 1px solid #ddd; }
  .tieu { position: sticky; top: 0; background: #2e7d32; color: #fff; padding: 6px 10px; }
  .noi { padding: 6px 10px; }
  .noi:nth-child(odd) { background: #f5f5f5; }
</style>
<div class="cuon">
  <div class="tieu">Chương 1 (dính khi cuộn)</div><div class="noi">Mục 1.1</div><div class="noi">Mục 1.2</div><div class="noi">Mục 1.3</div><div class="noi">Mục 1.4</div>
  <div class="tieu">Chương 2</div><div class="noi">Mục 2.1</div><div class="noi">Mục 2.2</div><div class="noi">Mục 2.3</div><div class="noi">Mục 2.4</div>
</div>
Kết quả hiển thị
.len-dau { position: fixed; right: 20px; bottom: 20px; z-index: 100; }

Cuộn trong khung để thấy tiêu đề chương dính lại. sticky cần ít nhất một giá trị top/bottom và không hoạt động nếu một tổ tiên có overflow: hidden.

z-index và ngữ cảnh xếp lớp

<style>
  .lop { position: absolute; width: 110px; height: 70px; border-radius: 8px; color: #fff; padding: 6px; font-size: 13px; }
  .l1 { background: #1565c0; top: 10px; left: 10px; z-index: 1; }
  .l2 { background: #2e7d32; top: 35px; left: 60px; z-index: 3; }
  .l3 { background: #e65100; top: 60px; left: 110px; z-index: 2; }
  .vung { position: relative; height: 150px; }
</style>
<div class="vung"><div class="lop l1">z-index 1</div><div class="lop l2">z-index 3</div><div class="lop l3">z-index 2</div></div>
Kết quả hiển thị

z-index chỉ có tác dụng với phần tử có position (khác static) hoặc là con flex/grid. Các thuộc tính như opacity < 1, transform, filter tạo ngữ cảnh xếp lớp mới: con bên trong không thể “vượt” lên trên phần tử ngoài nhóm dù z-index 9999.

float và clear

<style>
  .anh-trai { float: left; width: 110px; height: 80px; margin: 0 12px 6px 0; border-radius: 8px; background: #90a4ae; }
  .sau { clear: both; padding-top: 6px; color: #2e7d32; }
</style>
<div class="anh-trai"></div>
<p>Float đặt khối sang trái, văn bản chảy bao quanh như trong báo in. Ngày nay float chỉ nên dùng cho mục đích này; bố cục cột hãy dùng Flexbox hoặc Grid.</p>
<p class="sau">Đoạn có clear: both bắt đầu bên dưới ảnh.</p>
Kết quả hiển thị
Mẹo hay

Dùng inset: 0 thay cho top/right/bottom/left: 0 để phủ kín phần tử cha (lớp phủ modal, gradient trên ảnh).

Lưu ý

Phần tử absolute/fixed bị lấy khỏi luồng tài liệu, phần tử cha có thể co lại không còn chiều cao. Hạn chế dùng absolute để dựng bố cục chính.

Thực hành
  1. Làm thẻ sản phẩm có nhãn “Mới” ở góc và nút yêu thích.
  2. Tạo thanh menu dính đầu trang khi cuộn bằng sticky.
  3. Làm nút “lên đầu trang” cố định góc phải dưới.
  4. Tạo hộp thoại modal: lớp phủ fixed inset 0 và hộp ở giữa.
Tóm tắt bài học
  • static, relative, absolute, fixed, sticky.
  • absolute tính theo tổ tiên có position gần nhất.
  • z-index cần position; chú ý ngữ cảnh xếp lớp.
  • float chỉ cho ảnh trong văn bản; clear để thoát.