Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม

4 เหตุผลที่ z-index ไม่ทำงาน (และวิธีแก้ไข)

z-index คืออะไร? z-index เป็นคุณสมบัติ CSS ที่ให้คุณจัดตำแหน่ง HTML Elements เป็นชั้นๆ ทับกัน ดูเรียบง่ายแต่จริงๆ แล้วหลอกลวง

มีกฎแปลกๆ ไม่直覺 (non-intuitive) ทำให้มันไม่ทำงานкакที่คุณต้องการ—แม้ตั้ง z-index เป็น 999999!

บทความนี้อธิบายรายละเอียด 4 เหตุผลหลักที่ z-index ไม่ทำงาน คุณจะเรียนรู้ใช้ CSS นำ element ไปข้างหน้าหรือด้านหลัง element อื่น

1. Elements ใน Stacking Context เดียวกันจะแสดงตามลำดับการปรากฏ โดย element ที่มาหลังจะอยู่บน element ที่มาก่อน

ในตัวอย่างแรก เรามี Layout ง่ายๆ ประกอบ 3 Element หลัก:

  • รูปแมว
  • บล็อกสีขาวพร้อมข้อความ
  • รูปแมวตัวเดิมอีกตัว

HTML Markup:

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

ใน Layout นี้ เราอยากให้บล็อกสีขาวข้อความอยู่บนแมวทั้งสอง

ลองทำโดยเพิ่ม Negative Margins ใน CSS สำหรับรูปแมวทั้งสอง ทับบล็อกสีขาวเล็กน้อย:

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

แต่ผลลัพธ์เป็น:

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

แมวตัวแรกอยู่ใต้บล็อกเนื้อหาสีขาว ตามที่ต้องการ แต่แมวตัวที่สองอยู่บนบล็อก!

ทำไมจึงเกิดขึ้น?

เหตุผลคือ Natural Stacking Order บนหน้าเว็บ กฎเหล่านี้กำหนดว่า element ไหนอยู่บน ไหนอยู่ล่าง

แม้ Element จะไม่มี z-index ก็มีหลักเหตุผลว่าตัวไหนอยู่บน

ในกรณีแมวและบล็อกสีขาว ไม่มี z-index value ใดๆ ลำดับ Stacking ถูกกำหนดโดยลำดับการปรากฏ ตามกฎนี้ Element ที่มาหลังใน Markup จะอยู่บน Element ที่มาก่อน

(อ่านเพิ่มเติม Stacking Order Guidelines ที่ Mozilla Developer Network ที่นี่)

ในตัวอย่างแมวและบล็อกสีขาว ปฏิบัติตามกฎนี้ ดังนั้นแมวตัวแรกใต้บล็อกสีขาว และบล็อกสีขาวใต้แมวตัวที่สอง

เข้าใจ Stacking Order แล้ว แต่แก้ไข CSS ให้แมวตัวที่สองอยู่ใต้บล็อกสีขาวยังไง?

ดูเหตุผลที่สอง:

2. Element ไม่ได้ตั้งค่า Position

กฎอื่นที่กำหนด Stacking Order คือ Element มีการตั้ง Position หรือไม่

เพื่อตั้ง Position ให้ Element ให้เพิ่ม CSS Property position เป็นอะไรก็ได้ที่ไม่ใช่ static เช่น relative หรือ absolute (อ่านเพิ่มเติม บทความนี้)

ตามกฎนี้ Positioned Elements จะแสดงบน Unpositioned Elements

ดังนั้น ตั้งบล็อกสีขาวเป็น position: relative และทิ้งแมวทั้งสอง Unpositioned จะวางบล็อกสีขาวบนแมวใน Stacking Order

ลักษณะจะเป็น—คุณลองเล่น CodePen ด้านบนได้

4 เหตุผลที่ z-index ไม่ทำงาน (และวิธีแก้ไข)

ยินดีด้วย!

ต่อไป เราอยากหมุนแมวล่างให้กลับหัวลง ด้วย Property transform ทำให้แมวทั้งสองอยู่ใต้บล็อกสีขาว เหลือแค่หัวแมวลอยออกมา

แต่การทำนี้อาจก่อให้เกิดความสับสน z-index เพิ่มเติม เราจะแนะนำปัญหาและวิธีแก้ในส่วนต่อไป

3. การตั้งค่า CSS Properties บางอย่าง เช่น Opacity หรือ Transform จะวาง Element ใน Stacking Context ใหม่

เพิ่งกล่าวว่าเราอยากหมุนแมวล่างกลับหัวลง ทำได้โดยเพิ่ม transform: rotate(180deg)

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

แต่นี่ทำให้แมวล่างแสดงบนบล็อกสีขาวอีกครั้ง!

4 เหตุผลที่ z-index ไม่ทำงาน (และวิธีแก้ไข)

เกิดอะไรขึ้น??

คุณอาจไม่เจอบ่อย แต่อีกด้านของ Stacking Order คือ CSS Properties บางอย่าง เช่น transform หรือ opacity จะวาง Element เข้า Stacking Context ใหม่ของตัวเอง

หมายถึงการเพิ่ม transform ให้ .cat-bottom ทำให้มันพฤติกรรมเหมือนมี z-index: 0 แม้จะไม่ได้ตั้ง position หรือ z-index เลย! (W3.org มีเอกสารค่อนข้างหนาแน่นเกี่ยวกับการทำงานกับ Property opacity ที่นี่)

จำได้ไหม เราไม่เคยเพิ่ม z-index ให้บล็อกสีขาว แค่ position: relative เพียงพอที่จะวางบล็อกสีขาวบนแมวที่ Unpositioned

แต่เนื่องจาก Element .bottom-cat พฤติกรรมเหมือน Positioned Relatively พร้อม z-index: 0 การ Transform จึงวางมันบนบล็อกสีขาว

วิธีแก้คือ ตั้ง position: relative และระบุ z-index อย่างชัดเจน บนบล็อกสีขาวอย่างน้อย สามารถไปต่อโดยตั้ง position: relative และ z-index ต่ำกว่าบนแมว เพื่อความปลอดภัย

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

ในความคิดของผม การทำนี้จะแก้ไขปัญหา z-index พื้นฐานส่วนใหญ่ได้

ไปเหตุผลสุดท้ายที่ z-index ไม่ทำงาน นี่ซับซ้อนกว่า เพราะเกี่ยวกับ Parent และ Child Elements

4. Element อยู่ใน Stacking Context ต่ำกว่า เนื่องจาก Z-Index Level ของ Parent

ดูตัวอย่างโค้ด:

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

ที่นี่เรามี: เว็บไซต์ธรรมดาพร้อมเนื้อหา และแท็บสีชมพูข้างๆ บอก "Send Feedback" วางบนเนื้อหา

เมื่อคลิกรูปแมว Modal Window พร้อม Overlay พื้นหลังสีเทาโปร่งแสงจะเปิด

แต่แม้ Modal เปิดอยู่ แท็บข้างๆ ยังอยู่บน Overlay สีเทา เราต้องการให้ Overlay แสดงทับทุกอย่าง รวมแท็บข้างๆ

ดู CSS ของ Elements ที่เกี่ยวข้อง:

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

ทุก Element ตั้ง Position แล้ว และ Side Tab มี z-index: 5 วางบน Content Element ที่ z-index: 1

Modal มี z-index: 100 ควร วางบน Side Tab ที่ z-index: 5 แต่ Overlay Modal อยู่ใต้ Side Tab

ทำไมจึงเกิดขึ้น?

ก่อนหน้านี้เราพูดถึงปัจจัย Stacking Context เช่น Element มี Position Set หรือไม่ และลำดับใน Markup

แต่ด้านอื่นของ Stacking Context คือ Child Element จำกัดโดย Stacking Context ของ Parent

ดู Element ทั้งสามใกล้ชิด:

Markup ที่เรามี:

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

จาก Markup เห็นว่า Content และ Side Tab เป็น Siblings อยู่ระดับเดียวกันใน Markup (ต่างจาก Z-Index Level) และ Modal เป็น Child Element ของ Content Element

เพราะ Modal อยู่ใน Content Element z-index 100 ของมันมีผลแค่ภายใน Parent คือ Content Element เช่นถ้ามี Child Elements อื่นเป็น Siblings ของ Modal z-index จะวางบนหรือใต้กัน

แต่ z-index ของ Child Elements ไม่มีความหมายนอก Parent เพราะ Parent Content Element มี z-index ตั้งเป็น 1

ดังนั้น Children รวม Modal ไม่สามารถหลุดจาก z-index Level นั้นได้

(จดจำได้ด้วย Hidden Metaphor: ลูกอาจถูกจำกัดโดยพ่อแม่ และไม่สามารถหลุดพ้นได้)

มี 2 วิธีแก้:

วิธีแก้: ย้าย Modal ออกจาก Parent Content เข้าสู่ Main Stacking Context ของหน้า

Markup ที่แก้แล้ว:

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

ตอนนี้ Modal Element เป็น Sibling Element กับอีกสองตัว ทำให้ทั้งสามอยู่ใน Stacking Context เดียวกัน Z-Index Level ของแต่ละตัวจึงมีผลต่อกัน

ใน Stacking Context ใหม่ Elements จะแสดงจากบนลงล่าง:

  • Modal (z-index: 100)
  • Side Tab (z-index: 5)
  • Content (z-index: 1)

วิธีแก้ทางเลือก: ลบ Positioning จาก Content ให้มันไม่จำกัด Z-Index ของ Modal

หากไม่ต้องการหรือไม่สามารถเปลี่ยน Markup ให้แก้โดยลบ position setting จาก Content Element:

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

เนื่องจาก Content Element Unpositioned แล้ว จึงไม่จำกัด z-index ของ Modal Modal ที่เปิดจะวางบน Side Tab Element เนื่องจาก z-index สูงกว่า 100

แม้จะทำงานได้ แต่ผมชอบวิธีแรก

เพราะถ้าในอนาคตคุณต้อง Position Content Element อีกครั้ง มันจะกลับมาจำกัด Modal ใน Stacking Context อีกครั้ง

สรุป

หวังว่าบทช่วยสอนนี้มีประโยชน์! สรุป ปัญหา z-index ส่วนใหญ่แก้ได้โดยปฏิบัติตาม 2 กฎ:

  1. ตรวจสอบว่า Elements ตั้ง Position และ Z-Index Numbers ถูกต้องตามลำดับ
  2. แน่ใจว่าไม่มี Parent Elements จำกัด z-index Level ของ Children

แหล่งข้อมูล:

  • 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