Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình

4 lý do z-index không hoạt động (và cách khắc phục)

z-index là gì? z-index là thuộc tính CSS cho phép định vị element HTML thành các lớp chồng lên nhau. Nghe đơn giản, nhưng thực chất rất "giảo".

Có những quy tắc phi trực giác khiến nó không hoạt động như ý — ngay cả khi set z-index = 999999!

Bài viết giải thích chi tiết 4 lý do phổ biến nhất khiến z-index không chạy. Bạn sẽ học cách dùng CSS đưa element lên trước, hoặc đẩy lùi sau element khác.

1. Element cùng stacking context hiển thị theo thứ tự xuất hiện, element sau nằm trên element trước

Ví dụ đầu tiên, layout đơn giản 3 element chính:

  • Ảnh con mèo
  • Khối trắng có chữ
  • Ảnh con mèo nữa

HTML markup:

<div class="cat-top"></div> <div class="content__block"> Meow meow meow... </div> <div class="cat-bottom"></div>

Lý tưởng: khối trắng chữ nằm trên cả hai con mèo.

Thêm negative margin cho CSS cả hai ảnh mèo, để chồng lên khối trắng:

.cat-top { margin-bottom: -110px; } .cat-bottom { float: right; margin-top: -120px; }

Kết quả:

See the Pen Z-index: #1: set position, #2: natural stacking order, #3: CSS properties by Jessica (@thecodercoder) on CodePen.

Con mèo đầu đúng dưới khối trắng như mong muốn. Nhưng con mèo thứ hai lại nằm trên khối trắng!

Tại sao?

Do thứ tự chồng tự nhiên (natural stacking order) trên trang. Các quy tắc này quyết định element nào trên, nào dưới.

Dù element không set z-index, vẫn có quy luật ai lên trên.

Trường hợp này, không element nào có z-index. Thứ tự chồng theo thứ tự xuất hiện trong markup. Element xuất hiện sau nằm trên element xuất hiện trước.

(Đọc thêm stacking order guidelines tại Mozilla Developer Network ở đây.)

Ví dụ mèo và khối trắng tuân thủ quy tắc này. Con mèo đầu dưới khối trắng, khối trắng dưới con mèo thứ hai.

OK, stacking order ổn, nhưng làm sao sửa CSS cho con mèo thứ hai dưới khối trắng?

Xem lý do thứ hai:

2. Element không có position set

Một quy tắc khác quyết định stacking order: element có set position hay không.

Để set position cho element, thêm CSS property position bất kỳ giá trị nào khác static, như relative hoặc absolute. (Đọc thêm bài viết tôi viết về chủ đề này.)

Theo quy tắc này, element có position (positioned) sẽ hiển thị trên element không position (unpositioned).

Vậy set khối trắng position: relative, để hai con mèo không position. Khối trắng sẽ lên trên mèo trong stacking order.

Kết quả (cũng có thể test trên Codepen trên):

4 lý do z-index không hoạt động (và cách khắc phục)

Tuyệt!

Tiếp theo, muốn xoay con mèo dưới ngược 180 độ, dùng property transform. Cả hai mèo sẽ dưới khối trắng, chỉ lộ đầu.

Nhưng việc này gây thêm nhầm lẫn z-index. Giải quyết ở phần sau.

3. Set một số CSS property như opacity, transform khiến element vào stacking context mới

Như vừa nói, muốn xoay con mèo dưới ngược. Thêm transform: rotate(180deg).

.cat-bottom { float: right; margin-top: -120px; transform: rotate(180deg); }

Nhưng điều này khiến con mèo dưới lại hiển thị trên khối trắng!

4 lý do z-index không hoạt động (và cách khắc phục)

Sao lại vậy??

Bạn có thể ít gặp vấn đề này, nhưng khía cạnh khác của stacking order: một số CSS property như transform hoặc opacity sẽ đưa element vào stacking context mới của chính nó.

Có nghĩa là thêm transform cho .cat-bottom làm nó hành xử như có z-index: 0. Dù nó không set position hay z-index! (W3.org có tài liệu khá kỹ nhưng nặng nề về cách này hoạt động với opacity.)

Nhớ là chúng ta chưa thêm z-index cho khối trắng, chỉ position: relative. Đủ để khối trắng lên trên mèo không position.

Nhưng vì .cat-bottom hành xử như positioned với z-index: 0, transform nó đã đưa nó lên trên khối trắng.

Giải pháp: set position: relative và tường minh set z-index cho ít nhất khối trắng. Có thể tiến thêm bước: set position: relative và z-index thấp hơn cho mèo, để an toàn hơn.

.content__block { position: relative; z-index: 2; } .cat-top, .cat-bottom { position: relative; z-index: 1; }

Theo tôi, cách này giải quyết hầu hết vấn đề z-index cơ bản.

Chuyển đến lý do cuối cùng z-index không chạy. Phức tạp hơn, vì liên quan parent và child element.

4. Element ở stacking context thấp hơn do z-index của parent

Xem ví dụ code:

See the Pen Z-index: #4 different stacking contexts by Jessica (@thecodercoder) on CodePen.

Trang web đơn giản có content thường, và side tab hồng "Send Feedback" fixed trên content.

Khi click ảnh mèo, modal window với overlay xám mờ mở ra.

Tuy nhiên, ngay khi modal mở, side tab vẫn trên overlay xám. Muốn overlay hiển thị trên mọi thứ, kể cả side tab.

Xem CSS các element:

.content { position: relative; z-index: 1; } .modal { position: fixed; z-index: 100; } .side-tab { position: fixed; z-index: 5; }

Tất cả element có position set. Side tab z-index 5, trên content z-index 1.

Modal z-index 100 nên lên trên side tab z-index 5. Nhưng overlay modal lại dưới side tab.

Tại sao?

Trước đó đã nói các yếu tố stacking context: position set, thứ tự markup.

Nhưng khía cạnh khác: child element bị giới hạn bởi stacking context của parent.

Xem kỹ ba element:

Markup:

<section class="content"> <div class="modal"></div> </section> <div class="side-tab"></div>

Nhìn markup: content và side tab là sibling (cùng cấp). Modal là child của content.

Vì modal nằm trong content, z-index 100 của nó chỉ có hiệu lực bên trong parent content. Ví dụ: nếu có child khác sibling với modal, z-index của chúng quyết định ai trên ai.

Nhưng z-index của child那些 không có ý nghĩa ngoài parent, vì parent content có z-index = 1.

Con (child) không thể "vượt ra" khỏi z-index level của cha (parent).

(Nhớ bằng ẩn dụ hơi buồn: con bị giới hạn bởi cha, không thể tự do.)

Có vài giải pháp:

Giải pháp: Di chuyển modal ra khỏi parent content, vào stacking context chính của trang

Markup sửa:

<section class="content"></section> <div class="modal"></div> <div class="side-tab"></div>

Bây giờ modal là sibling của hai element kia. Đặt cả ba trong cùng stacking context, z-index của nhau ảnh hưởng lẫn nhau.

Trong stacking context mới, thứ tự hiển thị từ trên xuống:

  • modal (z-index: 100)
  • side tab (z-index: 5)
  • content (z-index: 1)

Giải pháp thay thế: Bỏ position khỏi content, để nó không giới hạn z-index của modal

Nếu không muốn/không thể đổi markup, sửa bằng cách bỏ position khỏi content:

.content { // Không set position } .modal { position: absolute; z-index: 100; } .side-tab { position: absolute; z-index: 5; }

Vì content giờ unpositioned, nó không còn giới hạn z-index của modal. Modal mở sẽ lên trên side tab nhờ z-index 100 cao hơn.

Cách này chạy được, nhưng tôi thích giải pháp đầu hơn.

Vì nếu sau này phải position content, nó lại giới hạn stacking order của modal.

Tóm tắt

Hy vọng hướng dẫn hữu ích! Tóm lại, hầu hết vấn đề z-index giải quyết được bằng 2 nguyên tắc:

  1. Kiểm tra element có set position và z-index đúng thứ tự không.
  2. Đảm bảo không có parent element giới hạn z-index level của child.

Tài liệu tham khảo:

  • W3.org: Transparency: the ‘opacity’ property
  • W3.org: Specifying the stack level
  • Mozilla Developer Network: The Stacking Context
  • PhilipWalton.com: What No One Told You About Z-index
  • Smashing Magazine: The Z-index CSS Property