Khi sử dụng position: fixed trong CSS, phần tử thường được căn chỉnh dựa trên khung nhìn (viewport) — tức là cửa sổ trình duyệt. Tuy nhiên, nếu một phần tử cha áp dụng bất kỳ thuộc tính nào sau đây, trình duyệt sẽ tạo ra một khối chứa mới (containing block), khiến phần tử con có position: fixed không còn gắn vào viewport mà chuyển sang định vị tương đối với chính phần tử cha đó:
transform: translateZ(0); /* bất kỳ giá trị nào khác 'none' */
perspective: 500px; /* giá trị khác 'none' */
filter: opacity(1); /* ví dụ: blur(0), brightness(1) */
backdrop-filter: contrast(1); /* cũng phải khác 'none' */
1. Cơ chế hoạt động của transform
Thuộc tính transform không chỉ thay đổi vị trí trực quan mà còn kích hoạt việc tạo lớp hiển thị độc lập (compositing layer). Khi điều này xảy ra:
- Trình duyệt tách phần tử ra khỏi luồng kết xuất thông thường.
- Lớp mới có hệ tọa độ riêng, và mọi phần tử con — kể cả những phần tử có
position: fixed— đều bị ràng buộc vào hệ tọa độ này. - Điều này dẫn đến hành vi "giả cố định": phần tử vẫn giữ thuộc tính
fixedvề mặt cú pháp, nhưng thực tế lại behave nhưabsoluteđối với khối chứa mới.
Ví dụ minh họa:
<div class="container">
<div class="overlay">Nội dung nổi</div>
</div>
.container {
transform: scale(1); /* đủ để kích hoạt lớp mới */
}
.overlay {
position: fixed;
top: 20px; /* giờ đây là cách 20px từ đỉnh .container, không phải viewport */
}
2. Vai trò của perspective
Khi thiết lập perspective, trình duyệt dựng một bối cảnh 3D riêng cho toàn bộ nội dung bên trong phần tử. Do đó:
- Các phép biến đổi 3D (như
rotateX,translateZ) được tính toán trong không gian đó. - Phần tử có
position: fixedcũng tuân theo bối cảnh này — nghĩa là gốc tọa độ của nó trở thành điểm tham chiếu của khối cha, chứ không còn là góc trên trái của viewport.
3. Ảnh hưởng từ filter và backdrop-filter
Cả hai thuộc tính này đều yêu cầu trình duyệt thực hiện xử lý hình ảnh ngoài luồng chính (offscreen rendering):
filteráp dụng hiệu ứng lên nội dung của phần tử.backdrop-filterxử lý vùng nền phía sau phần tử (ví dụ: hiệu ứng kính mờ).- Để đảm bảo hiệu ứng không bị cắt hoặc chồng lấn sai, trình duyệt tạo một lớp render riêng biệt — và do đó, cũng tạo ra một containing block mới.
Ngay cả khi giá trị filter không gây thay đổi thị giác rõ rệt (ví dụ: filter: blur(0) hay opacity(1)), cơ chế vẫn được kích hoạt.
4. Nguyên nhân cốt lõi: Lớp hiển thị và ngữ cảnh xếp chồng
Sự thay đổi hành vi của position: fixed bắt nguồn từ ba yếu tố kỹ thuật liên quan:
- Tạo khối chứa mới: Các thuộc tính nói trên buộc trình duyệt xác định lại "gốc" cho các phép tính vị trí.
- Phân tách lớp hiển thị: Mỗi lớp compositing có hệ tọa độ riêng, ngăn chặn can thiệp chéo giữa các hiệu ứng.
- Quy tắc đặc tả CSS: Theo tiêu chuẩn W3C, nếu phần tử có
position: fixednằm trong một "transform container", thì khối chứa của nó được xác định bởi container đó — không phải viewport.
5. Cách kiểm tra và khắc phục
Để xác minh xem một phần tử có đang nằm trong lớp compositing hay không:
- Mở Chrome DevTools → More Tools → Layers.
- Tìm phần tử có viền cam — đó là dấu hiệu của một compositing layer.
- Nếu thấy lớp đó bao phủ phần tử cha của modal/toast, khả năng cao nguyên nhân nằm ở
transform,filter, hoặcperspective.
Các giải pháp thực tế:
- Dịch chuyển phần tử ra ngoài cây DOM gây nhiễu: Đặt phần tử cần
fixedtrực tiếp dưới<body>, tránh bị bao bởi bất kỳ phần tử nào có thuộc tính kích hoạt layer. - Gỡ bỏ hoặc đặt lại thuộc tính gây ảnh hưởng: Nếu không cần hiệu ứng, thiết lập
transform: none,filter: none, v.v. - Thay thế bằng
position: absolute+ JavaScript cập nhật vị trí: Chỉ dùng khi bắt buộc, vì dễ gây trễ và khó bảo trì.
6. Bảng tổng hợp ảnh hưởng
| Thuộc tính | Mục đích sử dụng | Tác động lên fixed |
|---|---|---|
transform |
Biến đổi 2D/3D: dịch chuyển, xoay, phóng to | Tạo khối chứa mới → fixed định vị tương đối với phần tử cha |
perspective |
Thiết lập chiều sâu cho không gian 3D | Tương tự trên — do yêu cầu bối cảnh 3D riêng |
filter |
Áp dụng hiệu ứng hình ảnh lên phần tử | Bắt buộc offscreen rendering → tạo khối chứa mới |
backdrop-filter |
Áp dụng hiệu ứng lên vùng nền phía sau | Cùng cơ chế với filter |