เลื่อนเด้งบนเว็บไซต์ของคุณ
เผยแพร่แล้ว: 2022-03-10overscroll-behavior
ซึ่งใช้งานใน Chrome ในเดือนธันวาคม 2017 และใน Firefox ในเดือนมีนาคม 2018 ได้อธิบายไว้ในบทความนี้ด้วย ความเข้าใจที่ดีเกี่ยวกับผลกระทบนี้จะเป็นประโยชน์อย่างมากสำหรับการสร้างหรือออกแบบเว็บไซต์ที่มีองค์ประกอบคงที่การเด้งเลื่อน (บางครั้งเรียกว่า 'แถบยาง' หรือ 'การเลื่อนแบบยืดหยุ่น') มักใช้เพื่ออ้างถึงเอฟเฟกต์ที่คุณเห็นเมื่อคุณเลื่อนไปที่ด้านบนสุดของหน้าหรือองค์ประกอบ HTML หรือด้านล่างของ หน้าหรือองค์ประกอบบนอุปกรณ์ที่ใช้หน้าจอสัมผัสหรือแทร็คแพด และสามารถมองเห็นพื้นที่ว่างได้ครู่หนึ่งก่อนที่องค์ประกอบหรือหน้าจะเด้งกลับมาและจัดตำแหน่งตัวเองกลับไปที่ด้านบน/ด้านล่าง (เมื่อคุณปล่อยนิ้วหรือสัมผัส) คุณสามารถเห็นผลที่คล้ายคลึงกันเกิดขึ้นใน CSS scroll-snapping ระหว่างองค์ประกอบต่างๆ
อย่างไรก็ตาม บทความนี้เน้นที่การเลื่อนการเลื่อนเมื่อคุณเลื่อนไปที่ด้านบนสุดหรือด้านล่างสุดของหน้าเว็บ กล่าวอีกนัยหนึ่ง เมื่อสโครลพอร์ตถึงขอบเขตการเลื่อน
การรวบรวมข้อมูล วิธีที่มีประสิทธิภาพ
คุณรู้หรือไม่ว่า CSS สามารถใช้ในการรวบรวมสถิติได้? แท้จริงแล้ว มีแม้กระทั่งแนวทางเฉพาะ CSS สำหรับการติดตามการโต้ตอบ UI โดยใช้ Google Analytics อ่านบทความที่เกี่ยวข้อง →
ความเข้าใจที่ดีเกี่ยวกับการตีกลับของสกรอลล์นั้นมีประโยชน์มาก เนื่องจากจะช่วยให้คุณตัดสินใจได้ว่าจะสร้างเว็บไซต์อย่างไร และต้องการให้เพจเลื่อนอย่างไร
การเด้งเลื่อนเป็นสิ่งที่ไม่พึงปรารถนาหากคุณไม่ต้องการเห็นองค์ประกอบ fixed
ในการย้ายหน้า ตัวอย่างบางส่วน ได้แก่ เมื่อคุณต้องการแก้ไขส่วนหัวหรือส่วนท้ายในตำแหน่งใดตำแหน่งหนึ่ง หรือหากคุณต้องการแก้ไของค์ประกอบอื่นๆ เช่น เมนู หรือหากคุณต้องการให้หน้าเลื่อนสแนปที่ตำแหน่งใดตำแหน่งหนึ่งในการเลื่อนและ คุณไม่ต้องการให้มีการเลื่อนเพิ่มเติมเกิดขึ้นที่ด้านบนสุดหรือด้านล่างสุดของหน้าซึ่งจะทำให้ผู้เยี่ยมชมเว็บไซต์ของคุณสับสน บทความนี้จะเสนอวิธีแก้ไขปัญหาที่ต้องเผชิญเมื่อจัดการกับการเลื่อนการเลื่อนที่ด้านบนสุดหรือด้านล่างสุดของหน้าเว็บ
การเผชิญหน้าครั้งแรกของฉันกับเอฟเฟกต์
ครั้งแรกที่ฉันสังเกตเห็นผลกระทบนี้เมื่อฉันกำลังอัปเดตเว็บไซต์ที่ฉันสร้างขึ้นเมื่อนานมาแล้ว คุณสามารถดูเว็บไซต์ได้ที่นี่ ส่วนท้ายที่ด้านล่างของหน้าควรจะได้รับการแก้ไขในตำแหน่งที่ด้านล่างของหน้าและไม่ขยับเลย ในเวลาเดียวกัน คุณควรจะสามารถเลื่อนขึ้นและลงผ่านเนื้อหาหลักของหน้าได้ ตามหลักการแล้วมันจะทำงานดังนี้:

ปัจจุบันทำงานในลักษณะนี้ใน Firefox หรือเบราว์เซอร์ใดๆ บนอุปกรณ์ที่ไม่มีหน้าจอสัมผัสหรือแทร็คแพด อย่างไรก็ตาม ในขณะนั้น ฉันใช้ Chrome บน MacBook ฉันเลื่อนไปที่ด้านล่างของหน้าโดยใช้แทร็คแพด เมื่อพบว่าเว็บไซต์ทำงานไม่ถูกต้อง คุณสามารถดูสิ่งที่เกิดขึ้นได้ที่นี่:

ไม่นะ! นี่ไม่ใช่สิ่งที่ควรจะเกิดขึ้น! ฉันได้ตั้งค่าตำแหน่งของส่วนท้ายให้อยู่ที่ด้านล่างของหน้าโดยการตั้งค่าคุณสมบัติ position
CSS ให้มีค่า fixed
นี่เป็นเวลาที่ดีที่จะทบทวน position: fixed;
เป็น. ตามข้อกำหนด CSS 2.1 เมื่อมีการแก้ไข "กล่อง" (ในกรณีนี้คือส่วนท้ายสีน้ำเงินเข้ม) จะ "ได้รับการแก้ไขในส่วนที่เกี่ยวกับวิวพอร์ตและไม่เคลื่อนที่เมื่อเลื่อน" สิ่งนี้หมายความว่าส่วนท้ายไม่ควรขยับเมื่อคุณเลื่อนหน้าขึ้นและลง นี่คือสิ่งที่ทำให้ฉันกังวลเมื่อเห็นว่าเกิดอะไรขึ้นใน Chrome
เพื่อให้บทความนี้สมบูรณ์ยิ่งขึ้น ฉันจะแสดงให้คุณเห็นว่าหน้าเว็บเลื่อนไปมาอย่างไรบน Mobile Edge, Mobile Safari และ Desktop Safari ด้านล่าง ซึ่งต่างจากสิ่งที่เกิดขึ้นในการเลื่อนบน Firefox และ Chrome ฉันหวังว่าสิ่งนี้จะช่วยให้คุณเข้าใจดีขึ้นว่าโค้ดเดียวกันนี้ทำงานอย่างไรในรูปแบบต่างๆ ในปัจจุบัน การพัฒนาการเลื่อนที่ทำงานในลักษณะเดียวกันในเว็บเบราว์เซอร์ต่างๆ ถือเป็นเรื่องท้าทาย

กำลังค้นหาวิธีแก้ปัญหา
หนึ่งในความคิดแรกของฉันคือจะมีวิธีที่ง่ายและรวดเร็วในการแก้ไขปัญหานี้ในทุกเบราว์เซอร์ สิ่งนี้หมายความว่า ฉันคิดว่าฉันสามารถหาวิธีแก้ปัญหาที่ต้องใช้โค้ด CSS สองสามบรรทัดและไม่ต้องใช้ JavaScript ดังนั้น สิ่งแรกที่ฉันทำคือพยายามทำสิ่งนี้ให้สำเร็จ เบราว์เซอร์ที่ฉันใช้ในการทดสอบ ได้แก่ Chrome, Firefox และ Safari บน macOS และ Windows 10 และ Edge และ Safari บน iOS เวอร์ชันของเบราว์เซอร์เหล่านี้เป็นเวอร์ชันล่าสุดในขณะที่เขียนบทความนี้ (2018)
โซลูชัน HTML และ CSS เท่านั้น
ตำแหน่งสัมบูรณ์และสัมพัทธ์
สิ่งแรกที่ฉันพยายามคือ การใช้ตำแหน่งสัมบูรณ์และสัมพัทธ์เพื่อวางตำแหน่งส่วนท้าย เพราะฉันเคยชินกับการสร้างส่วนท้ายแบบนี้ แนวคิดคือตั้งค่าหน้าเว็บของฉันให้มีความสูง 100% เพื่อให้ส่วนท้ายอยู่ด้านล่างสุดของหน้าด้วยความสูงคงที่เสมอ ในขณะที่เนื้อหาใช้ความสูง 100% ลบความสูงของส่วนท้าย และคุณสามารถเลื่อนดูได้ อีกวิธีหนึ่ง คุณสามารถตั้งค่า padding-bottom
แทนการใช้ calc
และตั้งค่าความสูง body-container
เป็น 100% เพื่อให้เนื้อหาของแอปพลิเคชันไม่ทับซ้อนกับส่วนท้าย โค้ด CSS มีลักษณะดังนี้:
html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }
โซลูชันนี้ทำงานในลักษณะเดียวกับโซลูชันดั้งเดิม (ซึ่งเป็นเพียง position: fixed;
) ข้อดีอย่างหนึ่งของโซลูชันนี้เมื่อเปรียบเทียบกับการเลื่อนนั้นไม่ได้มีไว้สำหรับทั้งหน้า แต่สำหรับเนื้อหาของหน้าที่ไม่มีส่วนท้ายเท่านั้น ปัญหาที่ใหญ่ที่สุดของวิธีนี้คือใน Mobile Safari ทั้งส่วนท้ายและเนื้อหาของแอปพลิเคชันจะย้ายพร้อมกัน ทำให้วิธีนี้มีปัญหามากเมื่อเลื่อนอย่างรวดเร็ว:

เอฟเฟกต์อื่นที่ฉันไม่ต้องการนั้นสังเกตได้ยากในตอนแรก และฉันก็รู้เพียงว่ามันเกิดขึ้นหลังจากลองใช้วิธีแก้ปัญหาเพิ่มเติมแล้ว นี่คือการเลื่อนดูเนื้อหาของแอปพลิเคชันของฉันช้าลงเล็กน้อย เนื่องจากเรากำลังตั้งค่าความสูงของคอนเทนเนอร์การเลื่อนเป็น 100% ของตัวมันเอง จึงเป็นอุปสรรคต่อการเลื่อนตามการตวัด/โมเมนตัมบน iOS หากความสูง 100% นั้นสั้นกว่า (เช่น เมื่อความสูง 100% ที่ 2000px กลายเป็นความสูง 100% ที่ 900px) การเลื่อนตามโมเมนตัมจะแย่ลง การเลื่อนตามการตวัด/โมเมนตัมจะเกิดขึ้นเมื่อคุณใช้นิ้วสะบัดบนพื้นผิวของหน้าจอสัมผัสด้วยนิ้วของคุณ และเลื่อนหน้าด้วยตัวเอง ในกรณีของฉัน ฉันต้องการให้การเลื่อนตามโมเมนตัมเกิดขึ้น เพื่อให้ผู้ใช้สามารถเลื่อนได้อย่างรวดเร็ว ฉันจึงหลีกเลี่ยงโซลูชันที่กำหนดความสูง 100%

ความพยายามอื่น ๆ
หนึ่งในวิธีแก้ไขปัญหาที่แนะนำบนเว็บและฉันพยายามใช้กับโค้ดของฉัน ได้แสดงไว้ด้านล่างเป็นตัวอย่าง
html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }
รหัสนี้ทำงานบน Chrome และ Firefox บน macOS ในลักษณะเดียวกับโซลูชันก่อนหน้า ข้อดีของวิธีนี้คือเลื่อนไม่ได้จำกัดความสูง 100% ดังนั้นการเลื่อนตามโมเมนตัมจึงทำงานได้อย่างถูกต้อง อย่างไรก็ตาม บน Safari ส่วนท้ายจะหายไป:

บน iOS Safari ส่วนท้ายจะสั้นลง และมีช่องว่าง (หรือสีขาว) โปร่งใสเป็นพิเศษที่ด้านล่าง นอกจากนี้ ความสามารถในการเลื่อนดูหน้าจะหายไปหลังจากที่คุณเลื่อนไปที่ด้านล่างสุด คุณสามารถเห็นช่องว่างสีขาวด้านล่างส่วนท้ายได้ที่นี่:

โค้ดหนึ่งบรรทัดที่น่าสนใจที่คุณอาจเห็นเป็นจำนวนมากคือ: -webkit-overflow-scrolling: touch;
. แนวคิดเบื้องหลังนี้คืออนุญาตให้เลื่อนตามโมเมนตัมสำหรับองค์ประกอบที่กำหนด คุณสมบัตินี้อธิบายว่า "ไม่ได้มาตรฐาน" และ "ไม่ได้อยู่ในแทร็กมาตรฐาน" ในเอกสารประกอบ MDN ซึ่งแสดงเป็น “ค่าคุณสมบัติไม่ถูกต้อง” ภายใต้การตรวจสอบใน Firefox และ Chrome และจะไม่ปรากฏเป็นคุณสมบัติบนเดสก์ท็อป Safari ฉันไม่ได้ใช้คุณสมบัติ CSS นี้ในท้ายที่สุด
เพื่อแสดงตัวอย่างโซลูชันอื่นที่คุณอาจพบและผลลัพธ์อื่นที่ฉันพบ ฉันได้ลองใช้โค้ดด้านล่าง:
html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }
วิธีนี้ใช้งานได้จริงในเบราว์เซอร์เดสก์ท็อปต่างๆ การเลื่อนตามโมเมนตัมยังคงใช้งานได้ และส่วนท้ายได้รับการแก้ไขที่ด้านล่างและไม่ย้ายบนเว็บเบราว์เซอร์เดสก์ท็อป บางทีส่วนที่มีปัญหามากที่สุดของวิธีแก้ปัญหานี้ (และสิ่งที่ทำให้ไม่ซ้ำกัน) ก็คือบน iOS Safari ส่วนท้ายจะสั่นและบิดเบี้ยวเล็กน้อยเสมอ และคุณสามารถเห็นเนื้อหาด้านล่างทุกครั้งที่คุณเลื่อน
โซลูชั่นด้วย JavaScript
หลังจากลองใช้วิธีแก้ปัญหาเบื้องต้นโดยใช้แค่ HTML และ CSS ฉันก็ลองใช้โซลูชัน JavaScript บางอย่างดู ฉันต้องการเสริมว่านี่คือสิ่งที่ฉันไม่แนะนำให้คุณทำและควรหลีกเลี่ยงการทำ จากประสบการณ์ของผม มักจะมีวิธีแก้ปัญหาที่สวยงามและรัดกุมกว่าโดยใช้แค่ HTML และ CSS อย่างไรก็ตาม ฉันใช้เวลาไปมากในการทดลองใช้โซลูชันอื่นๆ แล้ว ฉันคิดว่าคงไม่เสียหายหากจะดูอย่างรวดเร็วว่ามีโซลูชันอื่นที่ใช้ JavaScript หรือไม่
สัมผัสเหตุการณ์
แนวทางหนึ่งในการแก้ปัญหาการเด้งเลื่อนคือการป้องกันเหตุการณ์ touchmove
หรือ touchstart
บน window
หรือ document
แนวคิดเบื้องหลังนี้คือการป้องกันเหตุการณ์การสัมผัสในหน้าต่างโดยรวม ในขณะที่กิจกรรมการสัมผัสในเนื้อหาที่คุณต้องการเลื่อนดูได้รับอนุญาต ตัวอย่างของรหัสเช่นนี้แสดงอยู่ด้านล่าง:
// Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)
ฉันลองใช้รหัสนี้หลายรูปแบบเพื่อให้การเลื่อนทำงานอย่างถูกต้อง การป้องกัน touchmove
บน window
ไม่ได้ทำให้เกิดความแตกต่าง การใช้ document
ไม่ได้ทำให้เกิดความแตกต่าง ฉันยังพยายามใช้ทั้ง touchstart
และ touchmove
เพื่อควบคุมการเลื่อน แต่ทั้งสองวิธีนี้ก็ไม่ต่างกัน ฉันได้เรียนรู้ว่าคุณไม่สามารถเรียก event.preventDefault()
ด้วยวิธีนี้ได้อีกต่อไปเนื่องจากเหตุผลด้านประสิทธิภาพ คุณต้องตั้งค่าตัวเลือก passive
false
ในตัวฟังเหตุการณ์:
// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})
ห้องสมุด
คุณอาจเจอห้องสมุดที่เรียกว่า “iNoBounce” ซึ่งสร้างขึ้นเพื่อ “หยุดเว็บแอป iOS ของคุณไม่ให้เด้งไปมาเมื่อเลื่อน” สิ่งหนึ่งที่ควรทราบเมื่อใช้ไลบรารีนี้ในขณะนี้เพื่อแก้ปัญหาที่ฉันได้อธิบายไว้ในบทความนี้คือคุณต้องใช้ -webkit-overflow-scrolling
สิ่งที่ควรทราบอีกประการหนึ่งคือวิธีแก้ปัญหาที่กระชับกว่าที่ฉันลงเอยด้วย (ซึ่งจะอธิบายในภายหลัง) ทำสิ่งที่คล้ายกับใน iOS คุณสามารถทดสอบได้ด้วยตัวเองโดยดูตัวอย่างใน GitHub Repository และเปรียบเทียบกับโซลูชันที่ฉันลงเอยด้วย
Overscroll พฤติกรรม
หลังจากลองใช้วิธีแก้ปัญหาเหล่านี้ทั้งหมดแล้ว ฉันพบข้อมูลเกี่ยวกับคุณสมบัติ CSS overscroll-behavior
คุณสมบัติ CSS overscroll-behavior
โครลถูกนำไปใช้ใน Chrome 63 ในเดือนธันวาคม 2017 และใน Firefox 59 ในเดือนมีนาคม 2018 คุณสมบัตินี้ ตามที่อธิบายไว้ในเอกสารประกอบ MDN “ช่วยให้คุณควบคุมพฤติกรรมการเลื่อนโอเวอร์โฟลว์ของเบราว์เซอร์ — จะเกิดอะไรขึ้นเมื่อขอบเขตของ ถึงพื้นที่เลื่อนแล้ว” นี่เป็นวิธีแก้ปัญหาที่ฉันใช้
ทั้งหมดที่ฉันต้องทำคือตั้งค่า overscroll-behavior
เป็น none
ใน body
ของเว็บไซต์ของฉัน และฉันสามารถปล่อยให้ position
ของส่วนท้าย fixed
แม้ว่าการเลื่อนตามโมเมนตัมจะใช้กับทั้งหน้า แทนที่จะใช้เนื้อหาที่ไม่มีส่วนท้าย โซลูชันนี้ดีเพียงพอสำหรับฉันและปฏิบัติตามข้อกำหนดทั้งหมดของฉัน ณ เวลานั้น และส่วนท้ายของฉันไม่เด้งบน Chrome โดยไม่คาดคิดอีกต่อไป อาจเป็นประโยชน์ที่จะทราบว่า Edge มีคุณสมบัตินี้ถูกตั้งค่าสถานะว่าอยู่ในระหว่างการพัฒนาในขณะนี้ overscroll-behavior
อาจถูกมองว่าเป็นการเพิ่มประสิทธิภาพหากเบราว์เซอร์ยังไม่รองรับ
บทสรุป
ถ้าคุณไม่ต้องการให้ส่วนหัวหรือส่วนท้ายคงที่ของคุณเด้งไปมาบนหน้าเว็บของคุณ คุณสามารถใช้คุณสมบัติ CSS overscroll-behavior
ได้แล้ว
แม้ว่าที่จริงแล้วโซลูชันนี้จะทำงานแตกต่างกันในเบราว์เซอร์ที่แตกต่างกัน (การตีกลับของเนื้อหาของหน้ายังคงเกิดขึ้นบน Safari และ Edge ในขณะที่ Firefox และ Chrome ไม่ทำงาน) จะทำให้ส่วนหัวหรือส่วนท้ายคงที่เมื่อคุณเลื่อนไปที่ด้านบนสุด หรือด้านล่างของเว็บไซต์ เป็นวิธีแก้ปัญหาที่รัดกุม และในทุกเบราว์เซอร์ที่ทดสอบ การเลื่อนตามโมเมนตัมยังคงใช้งานได้ ดังนั้นคุณจึงสามารถเลื่อนดูเนื้อหาของหน้าจำนวนมากได้อย่างรวดเร็ว หากคุณกำลังสร้างส่วนหัวหรือส่วนท้ายคงที่บนหน้าเว็บของคุณ คุณสามารถเริ่มใช้โซลูชันนี้ได้