ใน Chrome 22 ลักษณะการแสดงผลขององค์ประกอบ position:fixed
จะแตกต่างจากเวอร์ชันก่อนหน้าเล็กน้อย ตอนนี้องค์ประกอบ position:fixed
ทั้งหมดจะสร้างบริบทการซ้อนใหม่ ซึ่งจะเปลี่ยนลําดับการซ้อนของบางหน้า ซึ่งอาจทำให้เลย์เอาต์หน้าเว็บเสียหาย ลักษณะการทำงานใหม่นี้ตรงกับลักษณะการทำงานของเบราว์เซอร์ WebKit ในอุปกรณ์เคลื่อนที่ (iOS Safari และ Chrome สำหรับ Android)
Stacking Whats?
ทุกคนรู้จักและชื่นชอบ z-index
สำหรับการกำหนดลําดับความลึกขององค์ประกอบในหน้าเว็บ อย่างไรก็ตาม องค์ประกอบต่างๆ อาจมี z-index
ไม่เท่ากัน โดย z-index
ขององค์ประกอบหนึ่งๆ จะกำหนดลำดับขององค์ประกอบนั้นๆ เมื่อเทียบกับองค์ประกอบอื่นๆ ในบริบทการซ้อนเดียวกันเท่านั้น องค์ประกอบส่วนใหญ่ในหน้าเว็บจะอยู่ในบริบทการซ้อนรากรายการเดียว แต่องค์ประกอบที่มีตำแหน่งแบบสัมบูรณ์หรือแบบสัมพัทธ์ซึ่งมีค่า z-index
ที่ไม่ใช่ค่าอัตโนมัติจะสร้างบริบทการซ้อนของตนเอง (กล่าวคือ องค์ประกอบย่อยทั้งหมดจะจัดเรียงตามลําดับ z ภายในองค์ประกอบหลักและจะไม่สลับกับเนื้อหาจากภายนอกองค์ประกอบหลัก) ตั้งแต่ Chrome 22 องค์ประกอบ position:fixed
จะสร้างบริบทการซ้อนของตัวเองด้วย
หากต้องการทราบภาพรวมทั่วไปของบริบทการซ้อน โปรดอ่านบทความนี้ใน MDN
เปรียบเทียบ position:fixed
กับแอตทริบิวต์ position:sticky ใหม่: position:sticky
จะสร้างบริบทการซ้อนใหม่เสมอเพื่อใช้เป็นข้อมูลอ้างอิง
แรงจูงใจ
เบราว์เซอร์บนอุปกรณ์เคลื่อนที่ (Mobile Safari, เบราว์เซอร์ Android, เบราว์เซอร์ที่ใช้ Qt) จะใส่องค์ประกอบ position:fixed ในบริบทการซ้อนของตัวเองและดำเนินการมาระยะหนึ่งแล้ว (ตั้งแต่ iOS5, Android Gingerbread ฯลฯ) เนื่องจากช่วยให้สามารถเพิ่มประสิทธิภาพการเลื่อนบางอย่างได้ ซึ่งทำให้หน้าเว็บตอบสนองต่อการสัมผัสได้ดีขึ้นมาก เรานำการเปลี่ยนแปลงนี้มาใช้กับเดสก์ท็อปด้วยเหตุผล 3 ข้อดังนี้
- การแสดงผลที่ทำงานต่างกันในเบราว์เซอร์ "อุปกรณ์เคลื่อนที่" และ "เดสก์ท็อป" เป็นปัญหาสําคัญสำหรับผู้เขียนเว็บ CSS ควรทํางานเหมือนกันในทุกที่หากเป็นไปได้
- สำหรับแท็บเล็ต เราไม่แน่ใจว่าอัลกอริทึมการสร้างบริบทแบบซ้อนกันของ "อุปกรณ์เคลื่อนที่" หรือ "เดสก์ท็อป" เหมาะสมกว่ากัน
- การเพิ่มประสิทธิภาพการเลื่อนจากอุปกรณ์เคลื่อนที่ไปยังเดสก์ท็อปส่งผลดีต่อทั้งผู้ใช้และผู้เขียน
รายละเอียดของการเปลี่ยนแปลง
ตัวอย่างที่แสดงลักษณะการทำงานที่แตกต่างกันของเลย์เอาต์มีดังนี้ 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-Index เป็น 1 และ 3 (ตามลำดับ) ในบริบทรูท
หากกล่องสีน้ำเงินไม่ได้รับบริบทการซ้อนของตัวเอง ระบบจะคํานวณ z-index
ของกล่องสีส้มตามบริบทการซ้อนระดับรูท (พร้อมกับกล่องสีเขียวและสีชมพู) ดังนั้นกล่องสีส้มจึงซ้อนทับกับกล่องสีชมพูและสีเขียว
ดูรายละเอียดเพิ่มเติมเกี่ยวกับเกณฑ์การสร้างบริบทการซ้อน (และลักษณะการทํางานโดยทั่วไปของบริบทการซ้อน) ได้ที่บทความนี้ใน MDN ในตัวอย่างนี้ เวอร์ชันด้านขวาทำให้กล่องสีน้ำเงินมีบริบทการซ้อนของตัวเองเสมอเนื่องจากความทึบแสงน้อยกว่า 1 การเปลี่ยนแปลงลักษณะการทำงานที่ดำเนินการจะเพิ่มเกณฑ์อีกรายการหนึ่งสำหรับการสร้างบริบทการซ้อนที่แยกกัน ซึ่งก็คือองค์ประกอบที่มี position:fixed
การทดสอบและอนาคต
หากต้องการทดสอบว่าหน้าเว็บจะมีการเปลี่ยนแปลงหรือไม่ ให้ไปที่ about:flags
ของ Chrome แล้วเปิด/ปิด "องค์ประกอบตำแหน่งคงที่สร้างบริบทการซ้อน" หากเลย์เอาต์ทำงานเหมือนกันในทั้ง 2 กรณี แสดงว่าเรียบร้อย หากไม่ โปรดตรวจสอบว่าลักษณะของไอคอนเมื่อเปิดใช้ Flag นั้นยอมรับได้สำหรับคุณ เนื่องจากลักษณะดังกล่าวจะเป็นค่าเริ่มต้นใน Chrome 22
การเปลี่ยนแปลงนี้จะนําความสามารถหนึ่งออก นั่นคือความสามารถในการสลับเนื้อหาภายในซับต้นไม้ position:fixed กับเนื้อหาแบบไม่เลื่อนจากภายนอก ไม่น่าเป็นไปได้ที่นักพัฒนาเว็บจะตั้งใจทำเช่นนี้ และสามารถสร้างผลลัพธ์เดียวกันได้โดยการกำหนด DOM บางส่วนให้กับองค์ประกอบ position:fixed หลายรายการ ตัวอย่างที่ 1
https://codepen.io/wiltzius/pen/gcjCk
หน้านี้พยายามใช้ div ย่อย 2 รายการ (overlayA และ overlayB) ขององค์ประกอบ position:fixed และวาง 1 รายการไว้เหนือ div เนื้อหาแยกต่างหาก และอีก 1 รายการไว้ใต้ div เนื้อหาแยกต่างหากเดียวกัน แต่ตอนนี้การดำเนินการนี้ไม่สามารถทำได้เนื่องจากองค์ประกอบ position:fixed เป็นบริบทการซ้อนของตัวเอง และองค์ประกอบดังกล่าว (พร้อมกับองค์ประกอบย่อยทั้งหมด) จะอยู่เหนือหรือใต้ div เนื้อหาทั้งหมด
วิธีแก้ไขคือแยกการวางซ้อน 2 รายการออกเป็นองค์ประกอบแบบคงที่ตามตำแหน่ง แต่ละรายการเป็นบริบทการซ้อนของตัวเอง โดยรายการหนึ่งจะอยู่เหนือ div เนื้อหาและอีกรายการจะอยู่ใต้ div เนื้อหา ดูตัวอย่างที่แก้ไขแล้วซึ่งใช้งานได้ใน Chrome 21 และ 22
https://codepen.io/wiltzius/pen/vhFzG
เครดิตสำหรับที่มาของตัวอย่างนี้ต้องยกให้ hixie ที่ไม่มีใครเลียนแบบได้
Chrome เป็นเบราว์เซอร์เดสก์ท็อปรายแรกที่ทําให้องค์ประกอบ position:fixed สร้างบริบทการซ้อนของตัวเอง มาตรฐานที่เกี่ยวข้องคือข้อกำหนด z-index ของ CSS (ดูตัวอย่างได้ที่ https://www.w3.org/TR/CSS21/zindex.html) ยังไม่มีความเห็นเป็นเอกฉันท์เกี่ยวกับสิ่งที่ควรทำเกี่ยวกับความแตกต่างระหว่างเบราว์เซอร์บนอุปกรณ์เคลื่อนที่และเดสก์ท็อป แต่ Chrome เลือกที่จะเปลี่ยนไปใช้ลักษณะการทำงานแบบเดียวในทั้ง 2 แพลตฟอร์มในขณะนี้ เนื่องจากความสับสนที่เกิดจากการมีลักษณะการทำงาน 2 แบบที่แตกต่างกันในอุปกรณ์เคลื่อนที่และเดสก์ท็อป
อัปเดตเมื่อวันที่ 1 ต.ค. 2012: บทความเวอร์ชันแรกนี้ระบุว่าข้อกำหนด CSS z-index
มีการเปลี่ยนแปลงแล้วเพื่อให้สอดคล้องกับลักษณะการทำงานใหม่ขององค์ประกอบ position: fixed ข้อมูลนี้ไม่ถูกต้อง เราได้พูดคุยกันในรายการ www-style แล้ว แต่ยังไม่มีการเปลี่ยนแปลงในข้อกำหนด