"ดึงเพื่อแสดง" เป็นรูปแบบ UI ที่เนื้อหา (เช่น แถบค้นหาหรือตัวควบคุมการรีเฟรช) ถูกซ่อนไว้เหนือด้านบนของพื้นที่ที่เลื่อนได้เมื่อโหลดครั้งแรก และผู้ใช้สามารถดึงลง (เลื่อนขึ้น) เพื่อแสดงเนื้อหาได้ รูปแบบนี้มักใช้ในแอปบนอุปกรณ์เคลื่อนที่และเว็บแอปสำหรับแถบค้นหา ตัวกรอง และการควบคุมรองอื่นๆ ที่ควรเข้าถึงได้แต่ไม่แสดงทันที
พร็อพเพอร์ตี้ CSS scroll-initial-target มีวิธีประกาศที่ใช้ CSS เท่านั้นในการใช้รูปแบบนี้ การตั้งค่า scroll-initial-target: nearest ในองค์ประกอบเนื้อหาหลักจะทำให้คอนเทนเนอร์การเลื่อนแสดงผลโดยที่เนื้อหาที่ซ่อนอยู่เลื่อนออกไปจากมุมมอง ก่อนหน้านี้ นักพัฒนาแอปต้องอาศัย JavaScript (Element.scrollIntoView()) หรือตัวระบุส่วนย่อย URL (#content-id) เพื่อดำเนินการนี้ ซึ่งทั้ง 2 วิธีมีข้อจำกัดและใช้งานได้ยาก
วิธีการนำไปใช้งาน
วิธีใช้รูปแบบดึงเพื่อแสดง
- ตรวจสอบว่ามีคอนเทนเนอร์การเลื่อน: องค์ประกอบเป้าหมายต้องอยู่ภายในคอนเทนเนอร์การเลื่อน (องค์ประกอบที่มีรายการเพิ่มเติมที่อนุญาตให้เลื่อนได้ เช่น
overflow: auto) ซึ่งอาจเป็นองค์ประกอบระดับบนสุดใดก็ได้ รวมถึงองค์ประกอบ<html>ระดับรูท - กำหนดองค์ประกอบที่ซ่อนอยู่: วางเนื้อหาที่ต้องการซ่อน (เช่น แถบค้นหา) เป็นองค์ประกอบสืบทอดแรกภายในคอนเทนเนอร์การเลื่อน องค์ประกอบนี้จะเลื่อนออกจากมุมมองเมื่อโหลดครั้งแรก
- กำหนดเนื้อหาหลัก: วางองค์ประกอบเนื้อหาหลักไว้หลังองค์ประกอบที่ซ่อนอยู่ทันที นี่คือองค์ประกอบที่ผู้ใช้ควรเห็นเป็นอันดับแรก
- กำหนดเป้าหมายเนื้อหาหลัก: ใช้
scroll-initial-target: nearestกับองค์ประกอบเนื้อหาหลักเพื่อให้คอนเทนเนอร์การเลื่อนแสดงผลโดยเลื่อนเข้าไปในมุมมอง ซึ่งจะซ่อนองค์ประกอบที่อยู่ด้านบน - เพิ่มการสแนปการเลื่อน: เพื่อให้องค์ประกอบที่ซ่อนอยู่แสดงอย่างสมบูรณ์หรือซ่อนอย่างสมบูรณ์เสมอ (และไม่อยู่ในสถานะที่เลื่อนบางส่วน) ให้เพิ่ม
scroll-snap-type: y mandatoryลงในคอนเทนเนอร์การเลื่อน และเพิ่มscroll-snap-align: startลงในทั้งองค์ประกอบที่ซ่อนอยู่และองค์ประกอบเนื้อหาหลัก
โค้ดตัวอย่าง: ดึงเพื่อแสดงการค้นหา
/**
* ANCESTOR: Define the scroll container.
* Scroll snapping ensures the search bar is always
* either fully visible or fully hidden.
*/
.scroll-container {
height: 100vh;
overflow-y: auto;
scroll-snap-type: y mandatory;
}
/**
* HIDDEN ELEMENT: The search bar hidden above the fold on load.
* It has scroll-snap-align so it snaps into place when pulled down.
*/
.search-bar {
height: 60px;
scroll-snap-align: start;
}
/**
* MAIN CONTENT + TARGET: The element the user sees first.
* scroll-snap-align makes it a valid snap point.
* scroll-initial-target tells the browser to scroll here on
* initial render, hiding the search bar above it.
*/
.main-content {
scroll-snap-align: start;
scroll-initial-target: nearest;
}
การนำไปใช้เชิงกลยุทธ์และแนวทางปฏิบัติแนะนำ
- ควรใช้
scroll-initial-target: nearestเมื่อต้องการดึงดูดความสนใจของผู้ใช้ไปยังส่วนที่เฉพาะเจาะจงของพื้นที่ที่เลื่อนได้เมื่อโหลด และตั้งใจซ่อนหน่วย UI อุปกรณ์ต่อพ่วง เช่น แถบค้นหาที่ด้านบนสุด - อย่าสับสนระหว่างการโฟกัสนี้กับการโฟกัสการช่วยเหลือพิเศษ พร็อพเพอร์ตี้นี้จะย้ายเฉพาะวิวพอร์ตภาพเท่านั้น โดยจะไม่ย้ายโฟกัสของแป้นพิมพ์ คุณต้องจัดการ
element.focus()ด้วยตนเองหากต้องการให้เป้าหมายเป็นจุดเริ่มต้นสำหรับผู้ใช้แป้นพิมพ์ - อย่าใช้พร็อพเพอร์ตี้นี้หากต้องการภาพเคลื่อนไหว "การเลื่อน" ที่ราบรื่นเมื่อโหลด พร็อพเพอร์ตี้นี้ไม่ต่อเนื่องและจะตั้งค่าตำแหน่งทันทีในระหว่างระยะเลย์เอาต์
- อย่าตั้งค่า
scroll-initial-targetในองค์ประกอบหลายรายการภายในคอนเทนเนอร์ที่เลื่อนได้เดียวกัน หากมีองค์ประกอบหลายรายการที่ระบุscroll-initial-target: nearestเบราว์เซอร์จะเลือกองค์ประกอบที่ปรากฏเป็นอันดับแรกในลำดับแผนผัง DOM - ควรพิจารณาลำดับชั้นความสำคัญ: ส่วนย่อย URL (เช่น
example.com/#top) และพร็อพเพอร์ตี้scroll-startระดับคอนเทนเนอร์มีความสำคัญเหนือกว่าscroll-initial-target
กลยุทธ์สำรอง
สำหรับเบราว์เซอร์ที่ยังไม่รองรับ API ให้ใช้ JavaScript สำรอง โปรดทราบว่าสำหรับการดึงเนื้อหาเพื่อแสดง คุณต้องการให้เนื้อหาหลักเชื่อมโยงกับ start (ด้านบน) ของคอนเทนเนอร์
/**
* Progressive Enhancement Fallback
*/
document.addEventListener("DOMContentLoaded", () => {
// Check for native CSS support
if (!CSS.supports("scroll-initial-target", "nearest")) {
const targetContent = document.querySelector('.main-content.target');
if (targetContent) {
// Use behavior: "instant" to mimic the native CSS behavior
// 'block: start' should match your CSS 'scroll-snap-align' (or expected top position)
targetContent.scrollIntoView({ behavior: 'instant', block: 'start' });
}
}
});