Thuộc tính position
position kiểm soát cách phần tử được đặt vào trang. Kết hợp với top, right, bottom, left để xác định vị trí cụ thể.
Các giá trị
static (mặc định)
Phần tử nằm trong luồng bình thường. top/right/bottom/left và z-index không có tác dụng.
relative
Phần tử vẫn giữ chỗ trong luồng, nhưng dịch chuyển so với vị trí ban đầu.
.offset { position: relative; top: 10px; left: 20px; }
/* Chỗ cũ vẫn được giữ, phần tử dịch chuyển trực quan */
position: relativecũng tạo stacking context (ngữ cảnh z-index) cho con.
absolute
Phần tử thoát khỏi luồng (không chiếm chỗ trong layout). Vị trí tính từ tổ tiên position gần nhất (khác static), hoặc <html> nếu không có.
.card { position: relative; }
.badge {
position: absolute;
top: -8px; right: -8px;
}
fixed
Giống absolute nhưng vị trí tính từ viewport — phần tử cố định khi cuộn trang.
.sticky-nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; }
sticky
Kết hợp relative và fixed: phần tử cuộn cùng trang bình thường, nhưng dính vào ngưỡng chỉ định khi gần tới.
th { position: sticky; top: 0; background: white; }
stickychỉ hoạt động khi container cha có đủ chiều cao và khôngoverflow: hidden.
Tóm tắt so sánh
| Giá trị | Trong luồng? | Tham chiếu vị trí |
|---|---|---|
static |
Có | — |
relative |
Có (giữ chỗ) | Vị trí bản thân |
absolute |
Không | Tổ tiên positioned gần nhất |
fixed |
Không | Viewport |
sticky |
Có (trong container) | Container + viewport |
top, right, bottom, left
.box {
position: absolute;
top: 0; /* Cách cạnh trên 0px */
right: 10px; /* Cách cạnh phải 10px */
/* Không cần đặt tất cả 4 giá trị */
}
/* Căn giữa tuyệt đối */
.centered {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
Demo: Relative và absolute positioning
<h3>position: relative</h3>
<div class="flow-demo">
<div class="box normal">Box bình thường</div>
<div class="box relative-box">relative: top 15px, left 20px</div>
<div class="box normal">Box tiếp theo (chỗ cũ vẫn giữ)</div>
</div>
<h3>position: absolute (trong container relative)</h3>
<div class="card-demo">
<p>Card content — nội dung bài viết ngắn gọn.</p>
<span class="badge">BADGE</span>
<span class="corner-label">MỚI</span>
</div>
<h3>Căn giữa với absolute + transform</h3>
<div class="center-demo">
<div class="centered-box">Tôi ở giữa</div>
</div>
body { font-family: sans-serif; padding: 1rem; }
h3 { font-size: 1rem; color: #555; margin: 1rem 0 .4rem; }
.flow-demo { background: #f8f9fa; padding: 8px; border: 1px dashed #ccc; display: inline-flex; flex-direction: column; gap: 6px; }
.box { background: #cce5ff; border: 1px solid #4472c4; padding: 8px 12px; border-radius: 4px; }
.relative-box { position: relative; top: 15px; left: 20px; background: #fff3cd; border-color: #e09a00; }
.card-demo {
position: relative;
width: 240px; background: white; border: 1px solid #ddd;
border-radius: 8px; padding: 1rem; margin: 8px 0;
box-shadow: 0 2px 8px rgba(0,0,0,.1);
}
.badge {
position: absolute;
top: -10px; right: -10px;
background: #dc3545; color: white;
border-radius: 50%; width: 28px; height: 28px;
display: flex; align-items: center; justify-content: center;
font-size: .6rem; font-weight: bold;
}
.corner-label {
position: absolute;
top: 0; left: 0;
background: #28a745; color: white;
padding: 2px 8px; border-radius: 8px 0 8px 0;
font-size: .75rem; font-weight: bold;
}
.center-demo {
position: relative; height: 100px;
background: #f0f4ff; border: 1px dashed #4472c4;
border-radius: 4px; margin-top: 8px;
}
.centered-box {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
background: #4472c4; color: white;
padding: 8px 16px; border-radius: 4px;
white-space: nowrap;
}
Demo: Sticky header
<div class="scroll-container">
<div class="sticky-header">📌 Tiêu đề cố định (sticky)</div>
<div class="scroll-content">
<p>Cuộn xuống để thấy hiệu ứng sticky. Tiêu đề sẽ dính lại ở đầu container khi bạn cuộn.</p>
<p>Đây là đoạn văn thứ hai với một ít nội dung để trang thêm chiều cao.</p>
<p>Đoạn ba — tiếp tục cuộn...</p>
<p>Đoạn bốn — sticky vẫn đang hoạt động.</p>
<p>Đoạn năm — gần cuối rồi.</p>
<p>Đoạn sáu — hết nội dung, sticky sẽ cuộn đi cùng container.</p>
</div>
</div>
<p style="margin-top:1rem;font-size:.85em;color:#666">
ℹ️ Container có <code>height + overflow:auto</code> — cuộn bên trong để thấy sticky.
</p>
body { font-family: sans-serif; padding: 1rem; }
.scroll-container {
height: 220px;
overflow: auto;
border: 1px solid #ccc;
border-radius: 6px;
}
.sticky-header {
position: sticky;
top: 0;
background: #4472c4;
color: white;
padding: 10px 16px;
font-weight: bold;
font-size: 1rem;
z-index: 10;
box-shadow: 0 2px 4px rgba(0,0,0,.2);
}
.scroll-content {
padding: 12px 16px;
}
.scroll-content p {
margin: 0 0 12px;
padding: 10px;
background: #f0f4ff;
border-radius: 4px;
border-left: 3px solid #4472c4;
}
Bình luận