Lab
Smooth Scroll Lenis · a11y-safe
smooth scroll · drop-in

เลื่อนหน้าลื่น
แต่ถามก่อนว่าคุณโอเคไหม

Lenis ห่อ scroll จริงของเบราว์เซอร์ให้ลื่นแบบมี momentum โดยไม่ลบ native API ทิ้ง (ต่างจาก scroll-hijack library อื่น). ปัญหา: core ของ Lenis ไม่มี prefers-reduced-motion เลย — เราเลยห่ออีกชั้นเป็น lenis-kit ที่เปิด smooth เฉพาะคนที่ไม่ได้ปิด motion และสลับสดเมื่อผู้ใช้เปลี่ยนค่า OS

กดสวิตช์ FULL / AUTO / REDUCE (มุมขวาบน) — AUTO = ตามค่าเครื่อง (default), FULL = ลื่นเสมอ, REDUCE = native scroll ปกติ  ·  ตอนนี้: smooth · OS reduce
ปรับความหนืด (lerp) — น้อย = ลื่นยาว, มาก = ตามนิ้วไว:
ต่างจาก ScrollSmoother

Native API ยังทำงาน

Lenis ห่อ scroll จริง → position:sticky (แถบเมนูด้านบน + แถบนี้คือ sticky จริง), anchor link และ IntersectionObserver ยังใช้ได้ การ์ดข้างล่าง reveal ด้วย IntersectionObserver แท้ ๆ — พิสูจน์ว่าไม่ถูกลบทิ้งใต้ smooth scroll

stickytopbar + nav คือ sticky จริง
anchorกดเมนู → เลื่อนลื่นไปหัวข้อ
IO revealการ์ดนี้โผล่ด้วย IntersectionObserver
zero depsLenis ไม่กี่ KB · MIT

Parallax จาก scroll event

ตัวอักษรด้านล่างขยับตาม LenisKit.on('scroll') เมื่ออยู่โหมด REDUCE จะนิ่ง (อ่านค่า scroll ปกติแทน) — motion ที่ไม่จำเป็นถูกตัดให้คนที่ขอ

LENIS

ต่อ GSAP ScrollTrigger

Lenis + GSAP เป็นคู่หูคลาสสิก — ขับจาก rAF loop เดียวกัน lenis-kit ทำให้เหลือบรรทัดเดียว:

LenisKit.init();
LenisKit.connectGSAP(gsap, ScrollTrigger);
// gsap.ticker ขับ loop เดียว, lagSmoothing(0), ไม่ step ซ้ำ

หลัก a11y

smooth-scroll = ตระกูล scroll-hijack เดียวกับ GSAP ScrollSmoother — งานที่ a11y เข้มมักกังวล แต่ lenis-kit เปิด smooth เป็น progressive enhancement เฉพาะคนที่ไม่ได้ปิด motion ส่วนคนตั้ง reduce-motion ได้ native scroll เสมอ → ใช้ได้กับงานทุกประเภท โดยไม่ทิ้งใครไว้ข้างหลัง

lenis-kit เปิด smooth เฉพาะ AUTO + เครื่องไม่ได้ปิด motion — คนที่ตั้ง “ลดการเคลื่อนไหว” จะได้ native scroll เสมอ

วิธีใช้ — 2 บรรทัด

kit auto-load Lenis จาก CDN ให้เอง (ถ้าเน็ตพังก็ fallback native ไม่ทำหน้าล่ม):

<script src="lenis-kit.js"></script>
<script>LenisKit.init({ lerp: 0.1, anchors: true });</script>

API: set('full'|'reduced'|'auto') · scrollTo(target, opts) · status() · on('scroll'|'ready'|'change', cb) · start/stop/destroy · raw (instance ดิบ)

ครัว AI