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.
- 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
- 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
| position | Chiếm chỗ cũ | Mốc tọa độ | Dùng cho |
|---|---|---|---|
| static (mặc định) | Có | Không áp dụng top/left | Bình thường |
| relative | Có | Chính vị trí cũ | Dịch nhẹ; làm mốc cho con absolute |
| absolute | Không | Tổ tiên gần nhất có position khác static | Nhãn, nút đóng, chú thích đè ảnh |
| fixed | Không | Khung nhìn (viewport) | Thanh menu, nút lên đầu trang |
| sticky | Có | Khung cuộn gần nhất | Tiê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>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>.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>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>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).
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.
- Làm thẻ sản phẩm có nhãn “Mới” ở góc và nút yêu thích.
- Tạo thanh menu dính đầu trang khi cuộn bằng sticky.
- Làm nút “lên đầu trang” cố định góc phải dưới.
- Tạo hộp thoại modal: lớp phủ fixed inset 0 và hộp ở giữa.
- 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.