การเปลี่ยนแปลงการกองซ้อนที่จะเกิดขึ้นกับเอลิเมนต์ "ตำแหน่ง:คงที่"

Tom Wiltzius
Tom Wiltzius

ใน Chrome 22 ลักษณะการจัดวางขององค์ประกอบ position:fixed แตกต่างจากเวอร์ชันก่อนหน้าเล็กน้อย ตอนนี้องค์ประกอบ position:fixed ทั้งหมดจะสร้างบริบทการซ้อนใหม่แล้ว การดำเนินการนี้จะเปลี่ยนลำดับการเรียงซ้อนของบางหน้า ซึ่งอาจทำให้เลย์เอาต์หน้าเว็บเสียหาย ลักษณะการทำงานใหม่นี้ตรงกับลักษณะการทำงานของเบราว์เซอร์ WebKit บนอุปกรณ์เคลื่อนที่ (iOS Safari และ Chrome สำหรับ Android)

กองซ้อนคืออะไร

ทุกคนรู้จักและชื่นชอบ z-index ในการกำหนดลำดับความลึกขององค์ประกอบบนหน้าเว็บ ดัชนีลำดับ Z ทั้งหมดไม่ได้เท่ากัน แต่ z-index ขององค์ประกอบจะกำหนดลำดับที่สัมพันธ์กับองค์ประกอบอื่นๆ ในบริบทการกองซ้อนเดียวกันเท่านั้น องค์ประกอบส่วนใหญ่ในหน้าเว็บอยู่ในบริบทการเรียงซ้อนรากแบบเดี่ยว แต่องค์ประกอบที่มีตำแหน่งแบบสัมบูรณ์หรือค่อนข้างคงที่ซึ่งมีค่า z-index ที่ไม่ใช่แบบอัตโนมัติจะประกอบขึ้นเป็นบริบทการซ้อนของตนเอง (กล่าวคือ องค์ประกอบย่อยทั้งหมดจะเรียงลำดับแบบ z ภายในระดับบนสุด โดยไม่มีเนื้อหาจากภายนอกระดับบน) ตั้งแต่ Chrome 22 เป็นต้นไป องค์ประกอบ position:fixed จะสร้างบริบทการซ้อนของตนเองด้วย

อ่านภาพรวมทั่วไปของบริบทซ้อนกันบทความ MDN นี้

เปรียบเทียบ position:fixed กับแอตทริบิวต์ตำแหน่งใหม่:Sticky: สำหรับการอ้างอิง position:sticky จะสร้างบริบทการซ้อนใหม่เสมอ

แรงจูงใจ

เบราว์เซอร์ในอุปกรณ์เคลื่อนที่ (Safari บนอุปกรณ์เคลื่อนที่, เบราว์เซอร์ Android, เบราว์เซอร์ที่ใช้ Qt) จะใส่ตำแหน่ง:คงที่ ให้องค์ประกอบในบริบทการซ้อน (เช่น iOS5, Android Gingerbread และอื่นๆ) เนื่องจากทำให้สามารถเพิ่มประสิทธิภาพการเลื่อนบางอย่าง ซึ่งทำให้หน้าเว็บตอบสนองต่อการแตะได้มากขึ้น การเปลี่ยนแปลงนี้เกิดขึ้นบนเดสก์ท็อปด้วยเหตุผล 3 ประการ ดังนี้

  1. การมีพฤติกรรมการแสดงผลที่แตกต่างกันในเบราว์เซอร์ "อุปกรณ์เคลื่อนที่" และ "เดสก์ท็อป" เป็นอุปสรรคสำหรับผู้เขียนเว็บ เนื่องจาก CSS ควรทำงานเหมือนกันในทุกที่ที่เป็นไปได้
  2. สำหรับแท็บเล็ต เราจะอธิบายไม่ได้ว่าอัลกอริทึมการสร้างบริบทแบบซ้อนกันแบบใดที่เหมาะสมกว่าระหว่าง "อุปกรณ์เคลื่อนที่" หรือ "เดสก์ท็อป"
  3. การนำการเพิ่มประสิทธิภาพการเลื่อนดูจากอุปกรณ์เคลื่อนที่มาสู่เดสก์ท็อปเป็นสิ่งที่ดีทั้งสำหรับผู้ใช้และผู้เขียน

ข้อมูลจำเพาะของการเปลี่ยนแปลง

นี่คือตัวอย่างที่แสดงลักษณะการทำงานของเลย์เอาต์ที่แตกต่างกัน https://codepen.io/paulirish/pen/CgAof

การเปลี่ยนแปลงนี้ทำให้ทั้ง 2 เวอร์ชันจะแสดงผลเหมือนกับเวอร์ชันด้านขวา

ในตัวอย่างนี้ ช่องสีเขียวมีz-index: 1 กล่องสีชมพูมีz-index: 3 และช่องสีส้มมีz-index: 2 กล่องสีฟ้าเป็นระดับบนของกล่องสีส้มและมีposition:fixed

หากกล่องสีฟ้ามีบริบทการกองซ้อนของตัวเอง ระบบจะคำนวณ z-index ของกล่องสีส้มซึ่งสัมพันธ์กับบริบทการกองซ้อนของกล่องสีฟ้า เนื่องจากกล่องสีน้ำเงินมี z-index เป็น auto ทำให้มีระดับการซ้อนเป็น 0 ในบริบทกลุ่มราก ดังนั้นกล่องสีส้มจึงอยู่หลังกล่องสีเขียวและสีชมพูซึ่งมีดัชนี z เป็น 1 และ 3 (ตามลำดับ) ในบริบทราก

หากกล่องสีน้ำเงินไม่ได้รับบริบทการกองซ้อนของตัวเอง z-index ของช่องสีส้มจะได้รับการคำนวณโดยสัมพันธ์กับบริบทกลุ่มราก (พร้อมกับกล่องสีเขียวและสีชมพู) ดังนั้น กล่องสีส้มจึงถูกแทรกด้วยกล่องสีชมพูและสีเขียว

โปรดอ่านบทความ MDN นี้อีกครั้งสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเกณฑ์การสร้างบริบทแบบซ้อน (และลักษณะการทํางานทั่วไปของบริบทการกองซ้อน) ในตัวอย่าง เวอร์ชันด้านขวามือจะให้บริบทการซ้อนตัวเองแก่กล่องสีฟ้าเสมอเพราะความทึบแสงน้อยกว่า 1 การเปลี่ยนแปลงลักษณะการทำงานจะเพิ่มเกณฑ์อีก 1 ข้อได้อย่างมีประสิทธิภาพสำหรับการสร้างบริบทสแต็กที่แยกต่างหาก ซึ่งก็คือองค์ประกอบที่มีการกำหนดตำแหน่ง:คงที่

การทดสอบและอนาคต

หากต้องการทดสอบว่าหน้าของคุณจะมีการเปลี่ยนแปลงหรือไม่ ให้ไปที่ about:flags ของ Chrome และเปิด/ปิด "องค์ประกอบตำแหน่งคงที่สร้างบริบทซ้อนกัน" หากเลย์เอาต์ของคุณทำงานเหมือนกันในทั้ง 2 กรณี คุณก็มีการตั้งค่า หากไม่ถูกต้อง โปรดตรวจสอบว่าคุณยอมรับได้เมื่อเปิดการตั้งค่าสถานะไว้ เนื่องจากการตั้งค่าดังกล่าวเป็นค่าเริ่มต้นใน Chrome 22

การเปลี่ยนแปลงนี้จะนำความสามารถออก 1 อย่าง นั่นคือความสามารถในการแทรกเนื้อหาภายในแผนผังย่อยแบบอยู่กับที่ที่มีเนื้อหาแบบเลื่อนจากภายนอกได้ ไม่น่าเป็นไปได้ที่นักพัฒนาเว็บจะดําเนินการนี้โดยตั้งใจ และผลลัพธ์เดียวกันนี้สามารถสร้างขึ้นได้โดยการให้องค์ประกอบหลายตําแหน่ง:แก้ไขแล้วสําหรับส่วนต่างๆ ของ DOM ลองพิจารณาตัวอย่าง 2 ตัวอย่างต่อไปนี้เป็นตัวอย่าง

https://codepen.io/wiltzius/pen/gcjCk

หน้านี้จะพยายามใช้ div ย่อย 2 รายการ (overlayA และ OverlayB) ของตำแหน่ง:องค์ประกอบคงที่ และวางรายการหนึ่งเหนือ div เนื้อหาแยกต่างหากและอีก 1 ส่วนต่ำกว่า div เนื้อหาเดียวกันนั้น ตอนนี้ไม่สามารถดำเนินการเนื่องจากตำแหน่ง:Fixed Element เป็นบริบทแบบเรียงซ้อนของตัวเองและ (พร้อมด้วยองค์ประกอบย่อยทั้งหมด) จะเป็นตัวอย่างที่อยู่เหนือหรือใต้ div ของเนื้อหา 2 ทั้งหมดแต่ก่อนหน้านี้จะทำงานไม่ได้ใน 2 Chrome อีกต่อไป โปรดทราบว่า 2 เนื้อหานี้จะทำงานไม่ได้ใน Chrome 2 สคริปต์นี้

วิธีแก้ไขปัญหานี้คือสามารถแยกการวางซ้อน 2 รายการออกเป็นองค์ประกอบที่แก้ไขแล้วได้ บริบทแต่ละรายการจะเป็นบริบทแบบซ้อนของตัวเอง ซึ่งอาจอยู่เหนือ div เนื้อหาและอีก 1 ชั้นอาจอยู่ใต้ div เนื้อหา ดูตัวอย่างแบบคงที่ซึ่งใช้งานได้ใน Chrome 21 และ 22

https://codepen.io/wiltzius/pen/vhFzG

เครดิตสำหรับการก่อตั้งของตัวอย่างนี้ส่งไปที่ hixie inmitable

Chrome เป็นเบราว์เซอร์ในเดสก์ท็อปชนิดแรกที่ทำให้องค์ประกอบ "Position:" คงที่" สร้างบริบทการเรียงซ้อนของตนเอง มาตรฐานที่เกี่ยวข้องคือข้อกำหนดดัชนี z ของ CSS (ดู https://www.w3.org/TR/CSS21/zindex.html) ขณะนี้ยังไม่มีความเห็นพ้องกันว่าจะทำอย่างไรเกี่ยวกับความแตกต่างระหว่างเบราว์เซอร์ในอุปกรณ์เคลื่อนที่กับเดสก์ท็อป แต่เนื่องจากความสับสนเกี่ยวกับการมีลักษณะการทำงานที่ต่างกัน 2 อย่างในอุปกรณ์เคลื่อนที่กับเดสก์ท็อป Chrome จึงเลือกที่จะเปลี่ยนไปใช้ลักษณะการทำงานแบบเดียวในทั้ง 2 แพลตฟอร์มในขณะนี้

อัปเดตเมื่อ 1 ต.ค. 2012: เวอร์ชันเดิมของบทความนี้แนะนำให้มีการเปลี่ยนแปลงข้อกำหนดของ CSS z-index เพื่อให้สอดคล้องกับลักษณะการทำงานใหม่ของตำแหน่ง ซึ่งก็คือองค์ประกอบคงที่ ข้อมูลนี้ไม่ถูกต้อง มีการกล่าวถึงในรายการรูปแบบ www แต่ยังไม่ได้ทำการเปลี่ยนแปลงในข้อกำหนด