z-index quyết định thứ tự xếp chồng, nhưng chỉ so sánh được giữa các element cùng một stacking context.
.modal { position: fixed; z-index: 100; }
.tooltip { position: absolute; z-index: 10; }Hai điều kiện để z-index có tác dụng: element phải position khác static, hoặc là flex/grid item (trường hợp này z-index chạy mà không cần position).
Vì sao z-index: 9999 vẫn bị che — vì tổ tiên của nó đã tạo một stacking context có mức thấp hơn:
<div style="transform: translateZ(0); z-index: 1; position: relative">
<div style="z-index: 9999; position: absolute">Vẫn nằm dưới .sibling</div>
</div>
<div style="position: relative; z-index: 2" class="sibling">Trên</div>Con không bao giờ vượt ra khỏi thứ hạng của cha — 9999 chỉ có nghĩa bên trong cha đó.
/* tạo stacking context có chủ đích, không cần z-index */
.card { isolation: isolate; }Cách debug: trong DevTools, mở panel Layers hoặc kiểm tra từng tổ tiên xem có transform, filter, opacity < 1, will-change, contain hay không — đó là danh sách thủ phạm thường gặp.
Chốt: đừng chạy đua số. Dùng thang bậc cố định (10/100/1000) và isolation: isolate để nhốt z-index trong từng component.