Cara Membuat Snapping Scroll Sections dengan CSS Scroll-Snap (alternatif fullpage.js)

Diterbitkan: 2022-07-19

Dalam tutorial ini, kita akan membuat halaman yang di-snap dari satu bagian layar penuh ke bagian lain saat pengguna menggulir. Efek ini dipopulerkan oleh perpustakaan fullpage.js . Tapi sekarang, ada opsi yang lebih baik karena perubahan lisensi ke halaman penuh (Anda sekarang harus membayarnya), modul scroll-snap CSS yang baru, dan dukungan browser lengkap dari API pengamat persimpangan.

Jadi, jika Anda mencari alternatif fullpage.js, Anda bahkan mungkin tidak memerlukan seluruh pustaka, Anda bisa membuat kode sendiri!

Faktanya, efek gertakan adalah 100% CSS. JS hanya digunakan untuk memudarkan elemen ketika layar "terkunci" dalam tampilan.

Kami akan menggunakan "demo jepret gulir Taman Dinosaurus" ini oleh Michelle Barker yang tersedia di CodePen untuk inspirasi:

https://codepen.io/michellebarker/pen/PowYKXJ Lihat demo snap gulir Taman Dinosaurus Pena oleh Michelle Barker (@michellebarker) di CodePen.

Perhatian, Anda mungkin ingin melihatnya di layar yang lebih besar untuk merasakan efek "scroll snap" sepenuhnya.

Dengan menggunakan CSS yang digabungkan dengan Intersection Observer, kita akan membuat setiap bagian layar penuh dari snap-scroll halaman, dan memudarkan konten saat memasuki viewport.

Lebih baik lagi, hanya ~30 baris kode JS! Animasi dilakukan dengan CSS; yang perlu kita lakukan adalah memahami ketika bagian dan konten memasuki area pandang kita dengan JS.

1) Bangun Halaman Anda

Pertama, perlu membuat halaman, atau mengonfigurasi halaman yang sudah ada agar kompatibel dengan efek sederhana ini. Ada dua hal yang perlu diperhatikan di sini:

Kami menggunakan elemen <main> , yang berisi bagian kami. Elemen utama ini adalah 100vh, seperti juga masing-masing elemen <section> di dalamnya.

HTML:

<main> <section class="section section-1"> <div class="section__content" data-content >Konten di dalam</div> </section> <section class="section section-2"> <div class= "section__content" data-content >Konten di dalam</div> </section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">Jelajahi & Temukan</h3 > </header> <div class="section__content" data-content >Konten di dalam</div> </section> </main>

CSS:

/* Perilaku scroll */ @media (tinggi minimum: 30em) { main { scroll-snap-type: y wajib; tinggi: 100vh; overflow-y: gulir; } } .bagian { warna: putih; posisi: relatif; scroll-snap-align: tengah; tampilan: fleksibel; arah fleksibel: kolom; min-tinggi: 100vh; } @media (tinggi minimum: 30em) { .section { tinggi: 100vh; } }

2) Konfigurasikan Snapping dengan CSS

gambar-16-11

Di sini kita dapat melihat bahwa ada beberapa bagian, masing-masing dengan ketinggian 100vh.

Elemen <main>, juga 100vh, dengan overflow-y:scroll.

Bagi pengguna, perilaku gulir sama dengan halaman web default.

Jika Anda menambahkan CSS yang disebutkan di atas, efek gertakan sudah akan dimainkan. Mari kita lihat cara kerjanya.

Pertama, kueri " @media (min-height: 30em) " menonaktifkan efek gertakan untuk ukuran layar seluler yang terlalu pendek dalam hal ketinggian. Di bawah bagian utama, ada satu properti yang memungkinkan gertakan:

main { ....scroll-snap-type: y wajib; .... }

Ini adalah properti kecil yang keren "menetapkan seberapa ketat titik jepret diterapkan pada wadah gulir jika ada" (MDN).

Dan kemudian di bawah bagian kami, kami memiliki:

.section { ....scroll-snap-align: center; .... }

Properti ini "properti menentukan posisi jepret kotak sebagai penyelarasan area jepretnya (sebagai subjek penyelarasan) di dalam snapport wadah jepretnya (sebagai wadah penjajaran)" (MDN).

Pelajari lebih lanjut tentang modul scroll-snap CSS di sini:

Dan sesederhana itu. Anak-anak langsung di dalam wadah <main> (semua bagian), akan menggulir-snap ke tengah wadah <main>. Karena Main dan Section sama-sama 100vh, pengguliran akan terputus dari bagian ke bagian.

3) Memudar Konten Dalam Menggunakan Pengamat Persimpangan

Sekarang, kami memiliki efek gulir halaman penuh, dan jika Anda tidak ingin melakukan hal lain, Anda dapat melewati bagian ini dan menikmati situs web Anda. Namun, ketika setiap bagian halaman penuh masuk ke tampilan, saya ingin memudarkan konten di dalamnya - efek unik dan keren (juga yang mungkin dengan fullpage.js).

Untuk melakukan ini, kami akan menggunakan pengamat persimpangan untuk memahami posisi bagian dalam area pandang <main> kami.

const bagian = [...document.querySelectorAll("bagian"]); let options = { rootMargin: "0px", ambang batas: 0,75, }; const callback = (entri, pengamat) => { entries.forEach((entry) => { const { target } = entri; if (entry.intersectionRatio >= 0.75) { target.classList.add("is-visible") ; } else { target.classList.remove("terlihat"); } }); }; const observer = new IntersectionObserver(callback, options); section.forEach((section, index) => { const sectionChildren = [...section.querySelector("[data-content]").children]; sectionChildren.forEach((el, index) => { el.style .setProperty("--delay", `${index * 250}ms`); }); observer.observe(section); });

Ada dua hal yang dilakukan di sini. Pertama, ini mengidentifikasi saat bagian berada di viewport, dan saat masuk, menambahkan kelas CSS .is-visible . Saat meninggalkan viewport, itu menghapus kelas itu.

Selain itu, saat bagian ini memasuki viewport secara berurutan (satu demi satu) menetapkan properti penundaan selama 250 md pada setiap elemen turunan. Ini membuat efek fade yang terhuyung-huyung.

Ini hanya berlaku untuk anak-anak dalam elemen yang memiliki atribut konten-data. Jadi, Anda perlu menambahkannya ke pembungkus di sekitar konten halaman Anda jika Anda ingin efek fade.

Sekarang, untuk membuatnya berfungsi, kita perlu menyiapkan animasi fade-in untuk elemen yang memiliki kelas .is-visible yang ditambahkan.

@media (tinggi minimum: 30em) { .section__content > * { opacity: 0; mengubah: translate3d(0, 4rem, 0); transisi: opacity 800ms var(--delay), mengubah 800ms cubic-bezier(0.13, 0.07, 0.26, 0.99) var(--delay); } } .is-terlihat .section__content > * { opacity: 1; mengubah: translate3d(0, 1rem, 0); } .is-terlihat .section__img { opacity: 0.75; }

Jika kita merujuk kembali ke HTML dari demo awal, Anda akan melihat bahwa ada div yang membungkus konten dengan kelas .section__content, dan atribut data-content.

<main> <section class="section section-1"> <div class="section__content" data-content >Konten di dalam</div> </section> <section class="section section-2"> <div class= "section__content" data-content >Konten di dalam</div> </section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">Jelajahi & Temukan</h3 > </header> <div class="section__content" data-content >Konten di dalam</div> </section> </main>

Ini mengikat JS dan CSS kami bersama-sama. Opacity adalah 0 untuk konten hingga kelas .is-visible ditambahkan oleh pengamat persimpangan saat memasuki viewport. Ketika keluar, itu kembali ke opacity 0, jadi terlepas dari arah pengguliran Anda akan selalu ada umpan yang berlaku.

Akhirnya, delay yang diterapkan secara berurutan ke setiap elemen anak mengejutkan efek fade.

Perhatikan bagian ketiga. Header bagian tidak berada dalam bagian konten data, sehingga tidak akan memudar (sudah ada di sana).

Semua Kode

Berikut demonya:

isotropik-2022-07-15-at-15-00-58

Berikut semua kode yang kami gunakan dalam demo kami:

HTML

<main> <section class="section section-1"> <div class="section__content" data-content> <img class="section__img section__img--left" src="https://s3-us-west-2 .amazonaws.com/s.cdpn.io/85648/trex.svg" alt="T-rex" /> <h2>Konten di dalam</h2> <p>bla bla bla</p> </div> < /section> <section class="section section-2"> <div class="section__content" data-content> <h2>Konten di dalam</h2> <p>bla bla bla</p> </div> </ section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">Jelajahi & Temukan</h3> </header> <div class="section__content" data-content > <h2>Konten di dalam</h2> <p>bla bla bla</p> </div> </section> </main>

CSS

@media (tinggi minimum: 30em) { main { scroll-snap-type: y wajib; tinggi: 100vh; overflow-y: gulir; } } .section { warna: putih; posisi: relatif; scroll-snap-align: tengah; tampilan: fleksibel; arah fleksibel: kolom; min-tinggi: 100vh; } @media (tinggi minimum: 30em) { .section { tinggi: 100vh; } } @media (tinggi minimum: 30em) { .section__content > * { opacity: 0; mengubah: translate3d(0, 4rem, 0); transisi: opacity 800ms var(--delay), mengubah 800ms cubic-bezier(0.13, 0.07, 0.26, 0.99) var(--delay); } } .is-terlihat .section__content > * { opacity: 1; mengubah: translate3d(0, 1rem, 0); } .is-terlihat .section__img { opacity: 0.75; }

JS

const bagian = [...document.querySelectorAll("bagian"]); let options = { rootMargin: "0px", ambang batas: 0,75, }; const callback = (entri, pengamat) => { entries.forEach((entry) => { const { target } = entri; if (entry.intersectionRatio >= 0.75) { target.classList.add("is-visible") ; } else { target.classList.remove("terlihat"); } }); }; const observer = new IntersectionObserver(callback, options); section.forEach((section, index) => { const sectionChildren = [...section.querySelector("[data-content]").children]; sectionChildren.forEach((el, index) => { el.style .setProperty("--delay", `${index * 250}ms`); }); observer.observe(section); });

Kesimpulan

Ini adalah alternatif fullpage.js sempurna yang tidak hanya berhenti di antara bagian layar penuh. Kami juga menggunakan API pengamat persimpangan untuk memahami saat bagian memasuki halaman dan kemudian menerapkan animasi terhuyung-huyung secara dinamis. Anda dapat menggunakan contoh dasar ini untuk membangun dan membuat beberapa efek yang sangat keren dengan vanilla JS dan CSS yang minimal.