Trang chủ / Định Vị & Luồng Hiển Thị

Vì sao z-index đôi khi không hoạt động và stacking context kiểm soát các lớp chồng lấp

27/9/2026 ·

Vì sao z-index đôi khi không hoạt động và stacking context kiểm soát các lớp chồng lấp

Khi một menu thả xuống biến mất phía sau hình ảnh hero, hoặc một modal không chịu nằm trên header dính, cách sửa đầu tiên mà nhiều nhà phát triển tìm đến thường là tăng z-index. Đôi khi cách đó hiệu quả. Đôi khi mọi thứ không thay đổi, dù con số có lớn đến đâu. Hướng dẫn này giải thích cách bố cục CSS để chỉ ra vì sao z-index đôi khi không hoạt động và stacking context kiểm soát các lớp chồng lấp như thế nào.

z-index thực sự thay đổi điều gì

Thuộc tính z-index kiểm soát thứ tự của các phần tử được định vị dọc theo trục tưởng tượng hướng ra khỏi màn hình. Giá trị lớn hơn xuất hiện phía trên giá trị nhỏ hơn, trong khi giá trị âm có thể đặt một phần tử phía sau các phần tử anh em của nó. Bản thân z-index không di chuyển phần tử, không thay đổi kích thước của nó, cũng không làm nó hiển thị khi một thuộc tính khác đang ẩn nó.

Để z-index tham gia vào hệ thống xếp lớp bình thường, phần tử cũng phải được định vị. Thường nghĩa là position: relative, absolute hoặc fixed. Phần tử có position: static sẽ bỏ qua z-index, đây là một lý do phổ biến khiến một quy tắc có vẻ đúng lại không có tác dụng.

Một chi tiết quan trọng nữa là các giá trị z-index không mang tính toàn cục. Chúng không so sánh mọi phần tử trên toàn trang. Thay vào đó, chúng so sánh các phần tử anh em trong cùng một stacking context. Sự khác biệt này chính là cốt lõi của cách giải thích z-index và stacking context trong CSS theo thực tế.

Stacking context tạo các nhóm lớp riêng biệt

Một stacking context là một nhóm các lớp vô hình được trình duyệt xử lý như một đơn vị duy nhất. Các phần tử bên trong nhóm được sắp xếp tương đối với nhau, trong khi toàn bộ nhóm được sắp xếp đối với các nhóm khác. Nếu một stacking context cha nằm dưới một context khác, không có phần tử con nào có thể nổi lên trên context đó, kể cả với z-index: 999999.

Mẹo gỡ lỗi thực tế

Hãy tưởng tượng các bức tranh có khung trong một triển lãm. Các khung được treo ở những độ cao khác nhau trên tường. Một bức tranh có thể được di chuyển lên trong khung của chính nó, nhưng nó không thể nhảy lên vị trí trên một khung được treo thấp hơn. Khung chính là stacking context, và bức tranh là phần tử có z-index.

Các cách tạo stacking context phổ biến

  • Các phần tử được định vị với z-index khác auto: phần tử có position: relative và z-index: 1 tạo ra context riêng.
  • Các phần tử ở cấp gốc và bị transform: gốc tài liệu tạo thành context gốc, và các thuộc tính như transform, filter, perspective hoặc will-change thường tạo context mới.
  • Một số tính năng compositing và containment: opacity nhỏ hơn 1, mix-blend-mode, isolation, contain: paint, cùng các phần tử có vị trí fixed hoặc sticky cũng có thể tạo context tùy theo trình duyệt.

Vì những quy tắc này dễ bị bỏ qua, một style nhỏ như opacity: 0.99 hoặc transform: translateZ(0) có thể âm thầm thay đổi cấu trúc lớp. Phần tử vẫn trông gần như không đổi, nhưng các phần tử con của nó giờ sống trong một nhóm mới.

Vì sao z-index cao có vẻ thất bại

Nguyên nhân thường gặp nhất là context không kh��p. Một thẻ có thể chứa popup với z-index: 100, nhưng bản thân thẻ lại có z-index: 1. Popup có thể nổi lên trên mọi thứ bên trong thẻ, nhưng vẫn nằm dưới một thanh điều hướng riêng có z-index: 10. Con số hoạt động đúng; nó chỉ bị giới hạn trong phạm vi của thẻ.

Vấn đề tương tự xu���t hiện khi một phần tử cha nhận transform hoặc filter cho một hoạt động. Trước hiệu ứng, tooltip có thể nằm đúng phía trên nội dung lân cận. Sau hiệu ứng, phần tử cha tạo ra stacking context, và tooltip bị kẹt bên trong đó. Bỏ transform thường khôi phục hành vi cũ, nhưng giải pháp thực sự là hiểu phần tử nào nên sở hữu context.

Cách suy nghĩ đáng tin cậy về các lớp

Hãy bắt đầu bằng cách hỏi phần tử nào nên nằm trên phần tử nào. Sau đó, xác định tổ tiên chung thấp nhất chứa cả hai phần tử. Nếu hai phần tử nằm ở các nhóm khác nhau, hãy điều chỉnh các nhóm trước, rồi mới tinh chỉnh các giá trị z-index cục bộ của chúng.

Một trình tự gỡ lỗi thực tế trông như sau:

  • Xác nhận phần tử mục tiêu được định vị, hoặc gán cho nó position: relative nếu việc định vị là phù hợp.
  • Kiểm tra phần tử và các tổ tiên của nó về transform, filter, opacity, mix-blend-mode, isolation, contain hoặc z-index tường minh.
  • Kiểm tra xem phần tử muốn đặt cao hơn có thuộc một stacking context khác không.
  • Di chuyển ranh giới context bằng cách loại bỏ hiệu ứng không cần thiết hoặc nâng cấp wrapper đúng.
  • Dùng các giá trị z-index nhỏ, có ý nghĩa như 1, 2 và 10 thay vì các con số lớn tùy ý.

Thiết kế hệ thống xếp lớp dễ quản lý

Các dự án lớn dễ bảo trì hơn khi các giá trị lớp tuân theo một thang đơn giản. Ví dụ, nội dung bình thường có thể giữ ở auto, các lớp tương tác có thể dùng tầng thấp, điều hướng dính dùng tầng giữa, và hộp thoại tạm thời dùng tầng cao. Các con số chính xác không quan trọng bằng việc giữ chúng nhất quán.

Cũng hữu ích khi quyết định stacking context nên bắt đầu ở đâu. Một wrapper trang có thể chủ động cách ly nội dung của nó với các lớp ở cấp trình duyệt, trong khi portal của modal có th��� được đặt gần cuối tài liệu để chia sẻ context gốc với header. Những quyết định này giảm thiểu các tương tác bất ngờ sau này.

Cuối cùng, hãy nhớ rằng xếp lớp chỉ là một phần của trật tự trực quan. Một phần tử có thể có z-index đúng nhưng vẫn bị ẩn bởi overflow, chiều cao bằng 0, pointer-events, hoặc nền được vẽ bởi một phần tử anh em đến sau. Khi việc chồng lấp hoạt động kỳ lạ, hãy kiểm tra cả cây lớp và chính hộp.

Kết luận

z-index không phải là số ưu tiên toàn cục. Nó là một quy tắc thứ tự cục bộ bên trong một stacking context. Khi bạn xem trang như một tập hợp các nhóm lớp lồng nhau, những lỗi chồng lấp khó hiểu sẽ trở nên dễ đoán: tìm ranh giới nhóm, sửa ranh giới, rồi thiết lập thứ tự bên trong nó. Mô hình tư duy đó giúp việc gỡ lỗi và thiết kế xếp lớp CSS ngay từ đầu trở nên dễ dàng hơn.

Bài liên quan