ควบคุมการเลื่อนของคุณ - ปรับแต่งเอฟเฟกต์การดึงเพื่อรีเฟรชและเอฟเฟกต์เพิ่มเติม

TL;DR

พร็อพเพอร์ตี้ CSS overscroll-behavior ช่วยให้นักพัฒนาซอฟต์แวร์ลบล้าง ลักษณะการทำงานในการเลื่อนรายการเพิ่มเติมเริ่มต้นของเบราว์เซอร์เมื่อไปถึงด้านบน/ด้านล่างของ เนื้อหา กรณีการใช้งานรวมถึงการปิดใช้พุลเพื่อรีเฟรช บนอุปกรณ์เคลื่อนที่ การลบเอฟเฟกต์การเรืองแสงและแถบยาง รวมถึงป้องกันไม่ให้เนื้อหาในหน้าเว็บเลื่อนเมื่ออยู่ใต้โมดัล/โฆษณาซ้อนทับ

ข้อมูลเบื้องต้น

ขอบเขตการเลื่อนและโซ่การเลื่อน

การเชนแบบเลื่อนใน Chrome Android

การเลื่อนเป็นหนึ่งในวิธีพื้นฐานที่สุดในการโต้ตอบกับหน้าเว็บ แต่ รูปแบบ UX บางรูปแบบอาจจัดการได้ยากเพราะ พฤติกรรมที่เป็นค่าเริ่มต้น ตัวอย่างเช่น ดูตัวอย่างหน้าที่รวมแอปทั้งหมด รายการที่ผู้ใช้อาจต้องเลื่อนดู เมื่อถึงด้านล่างสุด คอนเทนเนอร์รายการเพิ่มเติมหยุดเลื่อนเนื่องจากไม่มีเนื้อหาให้บริโภคแล้ว กล่าวคือ ผู้ใช้ ถึง "ขอบเขตการเลื่อน" แต่โปรดสังเกตว่าจะเกิดอะไรขึ้นหากผู้ใช้ยังคง เลื่อน เนื้อหาด้านหลังลิ้นชักจะเริ่มเลื่อน การเลื่อนคือ ที่คอนเทนเนอร์ระดับบนสุดจะเข้ามาแทนที่ ของตัวหน้าหลักในตัวอย่าง

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

เอฟเฟกต์การดึงเพื่อรีเฟรช

ดึงเพื่อรีเฟรช คือท่าทางสัมผัสที่ใช้งานง่ายซึ่งเป็นที่นิยมในแอปบนอุปกรณ์เคลื่อนที่ เช่น Facebook และ Twitter ดึงความสนใจในฟีดโซเชียลและปล่อยข่าวจะสร้าง พื้นที่สำหรับโหลดโพสต์ล่าสุดเพิ่มเติม อันที่จริง UX นี้มี เป็นที่นิยมอย่างมากจนเบราว์เซอร์ในอุปกรณ์เคลื่อนที่อย่าง Chrome ใน Android นำมาใช้ แบบเดียวกัน การเลื่อนลงที่ด้านบนของหน้าจะรีเฟรชทั้งหน้า ดังนี้

การดึงเพื่อรีเฟรชที่กำหนดเองของ Twitter
เมื่อรีเฟรชฟีดใน PWA
การทำงานแบบพุลเพื่อรีเฟรชสำหรับ Chrome Android
จะรีเฟรชทั้งหมด

สำหรับสถานการณ์ต่างๆ อย่างเช่น Twitter PWA อาจเหมาะสมที่จะปิดใช้การดำเนินการ พุลเพื่อรีเฟรชแบบเนทีฟ เหตุผล ด้วยวิธีนี้ คุณอาจไม่ต้องการให้ผู้ใช้รีเฟรชหน้าเว็บโดยไม่ตั้งใจ มี คุณก็อาจเห็นภาพเคลื่อนไหวแบบรีเฟรช 2 ครั้งเช่นกัน หรืออาจกล่าวได้ว่า กำหนดค่าการทำงานของเบราว์เซอร์ โดยปรับให้มีความใกล้เคียงกับ การแสดงแบรนด์ สิ่งที่แย่คือการปรับแต่งประเภทนี้ ดึงออกได้ สุดท้ายนักพัฒนาซอฟต์แวร์ก็เขียน JavaScript ที่ไม่จำเป็น แบบไม่แพสซีฟ แตะ Listener (ซึ่งบล็อกการเลื่อน) หรือขีดทั้งหน้าเป็น 100vw/vh <div> (เพื่อป้องกันไม่ให้หน้าเว็บล้น) วิธีแก้ปัญหาเบื้องต้นเหล่านี้ เชิงลบที่มีการบันทึกไว้เป็นอย่างดี ที่มีผลต่อประสิทธิภาพการเลื่อนได้

เราน่าจะดีกว่านี้ได้

ขอแนะนำ overscroll-behavior

พร็อพเพอร์ตี้ overscroll-behavior คือฟีเจอร์ใหม่ของ CSS ที่ควบคุม ของสิ่งที่เกิดขึ้นเมื่อคุณเลื่อนคอนเทนเนอร์เกินเวลา (รวมถึง ) ซึ่งคุณสามารถใช้เพื่อยกเลิกการเชื่อมโยงการเลื่อน ปิดใช้/ปรับแต่ง การดึงเพื่อรีเฟรช ปิดใช้เอฟเฟกต์แถบยางใน iOS (เมื่อใช้ Safari ใช้งาน overscroll-behavior) และอื่นๆ สิ่งที่ดีที่สุดคือ การใช้ overscroll-behavior จะไม่ส่งผลเสีย ประสิทธิภาพหน้าเว็บ เช่น เคล็ดลับที่พูดถึงในบทนำ

พร็อพเพอร์ตี้ใช้ค่าที่เป็นไปได้ 3 ค่าดังนี้

  1. auto - ค่าเริ่มต้น การเลื่อนที่เกิดขึ้นบนองค์ประกอบอาจเผยแพร่ไปที่ เอลิเมนต์ระดับบน
  2. contain - ป้องกันการทำเชนการเลื่อน การเลื่อนไม่เผยแพร่ไปยังระดับบน แต่จะแสดงเอฟเฟ็กต์เฉพาะที่ภายในโหนด เช่น การเรืองแสงจากการเลื่อนไปจนสุด ส่งผลต่อ Android หรือเอฟเฟกต์ยางรัดใน iOS ซึ่งจะแจ้งเตือนผู้ใช้ เมื่อถึงขอบเขตการเลื่อน หมายเหตุ: การใช้ overscroll-behavior: contain ในองค์ประกอบ html ป้องกันไม่ให้เกิดการเลื่อนมากเกินไป การนำทาง
  3. ไม่มี - เหมือนกับ contain แต่ป้องกันเอฟเฟกต์การเลื่อนเกินภายใน ตัวโหนดเอง (เช่น การเรืองแสงของการเลื่อนไปจนสุดของ Android หรือแถบยางของ iOS)

เรามาดูตัวอย่างเพื่อดูวิธีใช้ overscroll-behavior กัน

ป้องกันไม่ให้การเลื่อนหลุดออกจากองค์ประกอบที่มีตำแหน่งคงที่

สถานการณ์ของกล่องแชท

เนื้อหาใต้หน้าต่างแชทจะเลื่อนเช่นกัน :(

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

สำหรับแอปนี้ การมีม้วนหนังสือที่เกิดขึ้นภายใน กล่องแชทจะอยู่แค่ในแชท ซึ่งเราทำได้โดยการเพิ่ม overscroll-behavior: contain ไปยังองค์ประกอบที่เก็บข้อความแชท:

#chat .msgs {
  overflow: auto;
  overscroll-behavior: contain;
  height: 300px;
}

โดยพื้นฐานแล้ว เรากำลังสร้างการแยกอย่างสมเหตุสมผลระหว่างการเลื่อนของช่องแชท บริบทและหน้าหลัก ผลลัพธ์สุดท้ายก็คือ หน้าหลักจะยังคงเดิมเมื่อ ผู้ใช้อยู่ที่ด้านบนสุด/ล่างสุดของประวัติการแชท การเลื่อนที่เริ่มต้นใน ช่องแชทไม่เผยแพร่

สถานการณ์การวางซ้อนหน้าเว็บ

อีกรูปแบบหนึ่งของ "underscroll" สถานการณ์สมมติเมื่อ คุณเห็นเนื้อหา เลื่อนลงหลังการวางซ้อนตำแหน่งคงที่ การแจกของรางวัลที่ตายแล้ว overscroll-behavior พร้อมใช้งานแล้ว เบราว์เซอร์จะพยายามให้เป็นประโยชน์ แต่ ท้ายที่สุด เว็บไซต์ก็จะดูมีข้อบกพร่อง

ตัวอย่าง - โมดัลที่มีและไม่มี overscroll-behavior: contain

ก่อน: เนื้อหาของหน้าเว็บจะเลื่อนอยู่ใต้โฆษณาซ้อนทับ
หลัง: เนื้อหาในหน้าเว็บไม่เลื่อนอยู่ใต้การวางซ้อน

กำลังปิดใช้การพุลเพื่อรีเฟรช

การปิดการดึงเพื่อรีเฟรชจะเป็น CSS บรรทัดเดียว เพียงป้องกัน ห่วงโซ่การเลื่อนในองค์ประกอบที่กำหนดวิวพอร์ตทั้งหมด ในกรณีส่วนใหญ่ นั่นก็คือ <html> หรือ <body>:

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

ด้วยการเพิ่มง่ายๆ นี้ เราจึงแก้ไขภาพเคลื่อนไหวแบบดึงเพื่อรีเฟรชสองครั้งใน การสาธิตช่องแชท และ ให้ใช้เอฟเฟกต์ที่กำหนดเองแทน ซึ่งใช้ภาพเคลื่อนไหวการโหลดที่ลื่นไหล กล่องจดหมายทั้งหมดจะเบลอเมื่อรีเฟรชกล่องจดหมาย:

ก่อน
หลัง

ต่อไปนี้เป็นตัวอย่างข้อมูลของ โค้ดแบบเต็ม:

<style>
  body.refreshing #inbox {
    filter: blur(1px);
    touch-action: none; /* prevent scrolling */
  }
  body.refreshing .refresher {
    transform: translate3d(0,150%,0) scale(1);
    z-index: 1;
  }
  .refresher {
    --refresh-width: 55px;
    pointer-events: none;
    width: var(--refresh-width);
    height: var(--refresh-width);
    border-radius: 50%;
    position: absolute;
    transition: all 300ms cubic-bezier(0,0,0.2,1);
    will-change: transform, opacity;
    ...
  }
</style>

<div class="refresher">
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
</div>

<section id="inbox"><!-- msgs --></section>

<script>
  let _startY;
  const inbox = document.querySelector('#inbox');

  inbox.addEventListener('touchstart', e => {
    _startY = e.touches[0].pageY;
  }, {passive: true});

  inbox.addEventListener('touchmove', e => {
    const y = e.touches[0].pageY;
    // Activate custom pull-to-refresh effects when at the top of the container
    // and user is scrolling up.
    if (document.scrollingElement.scrollTop === 0 && y > _startY &&
        !document.body.classList.contains('refreshing')) {
      // refresh inbox.
    }
  }, {passive: true});
</script>

การปิดใช้การเรืองแสงและแถบยางยืด

ในการปิดใช้เอฟเฟ็กต์การตีกลับเมื่อโดนขอบเขตการเลื่อน ให้ใช้ overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
ก่อน: เมื่อแตะขอบเขตการเลื่อนจะแสดงไฟเรืองแสง
หลัง: ปิดใช้เรืองแสง

การสาธิตแบบเต็ม

สรุปข้อมูลทั้งหมดก็คือ การใช้งานChatbox overscroll-behavior เพื่อสร้างภาพเคลื่อนไหวที่กำหนดเองแบบดึงเพื่อรีเฟรช และปิดใช้การเลื่อนไม่ให้ Escape วิดเจ็ตช่องแชท ซึ่งจะให้ผลดีที่สุด ประสบการณ์ของผู้ใช้คงยากที่จะบรรลุผลหากไม่มี CSS overscroll-behavior

ดูการสาธิต | แหล่งที่มา