Seperti kueri penampung; tetapi untuk kueri yang macet, terkunci, dan meluap.
Dipublikasikan: 15 Jan 2025
Chrome 133 dibuat berdasarkan kueri penampung dengan memperkenalkan kueri penampung status scroll. Status yang dikelola browser untuk posisi melekat, titik snap scroll, dan elemen yang dapat di-scroll kini dapat dikueri dan disesuaikan dari CSS.
Ringkasan
Sebelum kueri status scroll, Anda harus menggunakan JavaScript untuk memahami apakah elemen macet, terkunci, atau dapat di-scroll. Sekarang ada metode yang lebih berperforma di jalur standar untuk mengetahui informasi ini dan beradaptasi dengan sesuai. Ada juga cara baru untuk memicu animasi, yang membuka animasi yang dipicu scroll dari CSS.
Berikut adalah ringkasan kueri status yang tersedia mulai Chrome 133:
- Status macet:
- Memicu perubahan gaya saat elemen menempel ke tepi.
- Status snap:
- Memicu perubahan gaya saat elemen disambungkan ke sumbu.
- Status yang dapat di-scroll:
- Memicu perubahan gaya saat elemen meluap.
Kabar baiknya adalah semua yang telah Anda pelajari dari kueri penampung akan membantu Anda menggunakan kueri status scroll.
Ada juga wilayah yang belum dijelajahi antara animasi yang didorong scroll dan kueri penampung status scroll; kita perlu bereksperimen dengan pengaturan waktu dan konteks untuk mengetahui apakah animasi yang didorong scroll atau animasi status scroll yang dipicu scroll akan menjadi yang terbaik. Video dan demo berikut mengilustrasikan masalah; animasi yang dipicu sticky dibandingkan dengan animasi yang didorong scroll.
Kueri status scroll pertama
Langkah pertama adalah menentukan penampung, menggunakan nilai baru untuk properti container-type
. Seperti kueri penampung, elemen yang ingin Anda buat kuerinya adalah elemen yang Anda beri container-type
dan secara opsional container-name
. Dengan kueri status scroll, Anda memberikan elemen yang terkunci, macet, atau memiliki container-type: scroll-state
tambahan.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
}
Langkah kedua adalah memilih turunan penampung tersebut yang akan merespons status. Seperti kueri penampung, elemen ini tidak boleh sama dengan elemen yang memiliki container-type
.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
Langkah ketiga adalah mencobanya. Contoh CSS berikut akan menata gaya latar belakang menjadi merah saat elemen .stuck-top
menempel ke bagian atas di 0
. Dengan beberapa baris tambahan ke CSS yang telah kita tulis dan elemen penampung tambahan yang mem-proxy status browser, komponen kita akan jauh lebih cerdas dalam memahami lingkungannya.
Progressive Enhancement
Aturan dan bertingkat @supports
memungkinkan Anda menambahkan progressive enhancement atau penggunaan fitur bersyarat hanya dalam beberapa baris kode tambahan:
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
@supports (container-type: scroll-state) {
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
}
Selain itu, jangan lupa untuk menggunakan @media (prefers-reduced-motion: no-preference) {}
di sekitar gerakan, jika Anda akhirnya menganimasikan elemen di sekitar halaman dengan kueri status scroll.
Kasus Penggunaan
Macet
Mungkin bagian ini sebaiknya disebut "situasi sulit?" Ini adalah kumpulan kecil kasus penggunaan status melekat, ditambah bagian bonus ide yang perlu dibuat.
@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}
Menambahkan bayangan saat macet
Salah satu kasus penggunaan yang paling umum untuk kueri yang macet adalah untuk menu navigasi yang ingin menambahkan box-shadow
saat macet, sehingga menu tersebut dapat muncul mengambang di atas konten yang di-overlay.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
transition: box-shadow .3s ease;
@container scroll-state(stuck: top) {
box-shadow: var(--shadow-5);
}
}
}
Mengaktifkan header yang macet saat ini
Skenario masukan UI melekat umum lainnya adalah menandai elemen yang saat ini macet. Dalam daftar band yang diurutkan menurut abjad, hal ini dapat sangat membantu dan mendukung pengalaman.
.sticky-slide {
dt {
container-type: scroll-state;
position: sticky;
inset-block-start: 0;
inset-inline: 0;
> header {
transition:
background .3s ease,
box-shadow .5s ease;
@container scroll-state(stuck: top) {
background: hsl(265 100% 27%);
box-shadow: 0 5px 5px #0003;
}
}
}
}
Berikut adalah varian lain, dengan header di sisi item daftar. Ada banyak kemungkinannya.
Overflow ide
Berikut adalah daftar demo melekat yang mungkin menginspirasi Anda untuk menambahkan sedikit bumbu ke demo, atau menghapus JavaScript-nya, dengan kueri status scroll. Sebaiknya coba buat aplikasi yang Anda sukai. Hal ini akan membantu Anda mengingat sintaks dan ide 😏.
- https://codepen.io/BlogFire/pen/PoGMjaX - varian sticky note
- https://codepen.io/mikegolus/pen/jOZzRzw - menambahkan bayangan ke tabel saat menempel
- https://codepen.io/MarcRay/pen/PomBeP - menu navigasi di bawah header muncul saat pemicu diaktifkan
- https://codepen.io/kevinpowell/pen/OqKJjK - footer navbar reveal
- https://codepen.io/abhisekz-the-decoder/pen/eKaLRd - header kartu melekat
- https://codepen.io/tutsplus/pen/abojPjP - pricing header shadow on trigger
- https://codepen.io/kevinpowell/pen/KEjMEv - judul sidebar bagian yang melekat
Diambil
Dengan kueri status yang disematkan, kita dapat menghapus beberapa tanggung jawab dari JavaScript dan Peristiwa Snap, serta memindahkan penanganan ke CSS.
@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}
Pengingat kecil, jika Anda melewati bagian Kueri status scroll pertama, penampung untuk kueri snap adalah elemen dengan scroll-snap-align
di dalamnya, dan elemen yang dapat beradaptasi harus merupakan turunan dari elemen tersebut. Artinya, ada tiga elemen yang diperlukan untuk menyiapkannya:
a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
⤷ a child of the snap target that can query the container for snap state
Meningkatkan item yang diambil secara visual
Hal ini sangat umum dengan penggeser yang dijepret di tengah untuk menyoroti atau menampilkan item yang dijepret di tengah. Dalam contoh testimonial ini, kata kunci not
digunakan sehingga semua testimonial yang tidak di-snap memiliki opasitas rendah, sedangkan testimonial yang di-snap berada dalam status presentasi alaminya.
.demo {
overflow: auto hidden;
scroll-snap-type: x mandatory;
> article {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
> * {
transition: opacity .5s ease;
@container not scroll-state(snapped: x) {
opacity: .25;
}
}
}
}
}
Menampilkan teks untuk item yang diambil
Ini adalah contoh yang baik tentang cara kueri status scroll mengaktifkan animasi yang dipicu scroll. Ini juga merupakan contoh yang baik tentang kapan mengikuti gerakan yang dikurangi akan bernilai dalam CSS.
.demo {
overflow-x: auto;
scroll-behavior-x: contain;
scroll-snap-type: x mandatory;
> .card {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
figcaption {
transform: translateY(100%);
@container scroll-state(snapped: x) {
transform: translateY(0);
}
}
}
}
}
}
Menganimasikan elemen slide
Animasi elemen slide show atau presentasi saat memberikan presentasi adalah hal yang umum. Dulu, menulis observer interseksi untuk hal ini cukup menjengkelkan, yang hanya menetapkan class pada slide. Sekarang kita tidak memerlukan JavaScript.
html {
scroll-snap-type: y mandatory;
}
section {
container-type: scroll-state;
scroll-snap-align: start;
scroll-snap-stop: always;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
> h1 {
transition: opacity .5s ease, transform .5s var(--ease-spring-3);
transition-delay: .5s;
opacity: 0;
transform: scale(1.25);
@container scroll-state(snapped: block) {
opacity: 1;
transform: scale(1);
}
}
}
}
}
Anda mungkin melihat bahwa semua kueri status CSS yang diambil berperilaku seperti scrollsnapchanging
, bukan scrollsnapchange
. Hal ini memberi Anda hook paling awal untuk memberikan masukan visual tentang elemen yang diambil. Jika terlalu cepat, pertimbangkan peristiwa JavaScript.
Dapat di-scroll
Kueri status yang dapat di-scroll akan sangat membantu dalam menampilkan kemampuan visual saat area scroll benar-benar dapat di-scroll. Sebelum kueri status scroll, informasi ini sulit diketahui.
@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}
Menunjukkan scroll dengan bayangan
Ada trik CSS terkenal dari Lea Verou yang menggunakan background-attachment: local
untuk mendapatkan efek yang mirip dengan ini, serta cara melakukannya dengan animasi berbasis scroll. Setiap teknik memiliki konsekuensi. Kita harus mempelajari kapan dan di mana setiap teknik ini paling sesuai.
Contoh berikut menggunakan satu elemen melekat yang membentang di scrollport. Gradien di bagian atas dan gradien di bagian bawah memiliki opasitas yang dianimasikan dengan @property
saat kueri status scroll kontekstual diterapkan: @container scroll-state(scrollable: top)
.
Perhatikan juga bahwa ini adalah penampung pertama yang merupakan penampung size
dan scroll-state
.
.scroll-container {
container-type: scroll-state size;
overflow: auto;
&::after {
content: " ";
background: var(--_shadow-top), var(--_shadow-bottom);
transition:
--_scroll-shadow-color-1-opacity .5s ease,
--_scroll-shadow-color-2-opacity .5s ease;
@container scroll-state(scrollable: top) {
--_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
}
@container scroll-state(scrollable: bottom) {
--_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
}
}
}
Perintah panah
Terkadang, menampilkan panah dapat membantu pengguna mengetahui bahwa area dapat di-scroll. Ini cenderung mengarah ke arah yang dapat di-scroll, dan menghilang setelah tidak diperlukan lagi. Anda dapat melakukannya dengan kode berikut.
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
}
@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
rotate: .5turn;
}
Kembali ke atas
Interaksi status scroll populer lainnya adalah tombol praktis "scroll ke atas". Kode berikut menyebabkan tombol scroll ke atas menghilang saat tidak ada tempat untuk men-scroll ke atas.
Solusi ini sedikit terbalik, tetapi memungkinkan Anda mengurangi jumlah CSS. Tempat alami tombol berada dalam tampilan, jadi Anda perlu memberi tahu tombol untuk disembunyikan jika tidak ada tempat untuk men-scroll ke atas lagi.
@container not scroll-state(scrollable: top) {
translate: 0 calc(100% + 10px);
}
Studi lanjutan
Jika Anda mencari informasi selengkapnya, berikut beberapa referensi yang mencakup berbagai hal, mulai dari detail spesifikasi hingga artikel menarik lainnya yang membahas topik ini:
- Apa lagi yang dapat kita masukkan ke dalam kueri penampung? https://github.com/w3c/csswg-drafts/issues/5989
- Penjelasan scroll-state() - https://drafts.csswg.org/css-conditional-5/scroll_state_explainer.md
- Spesifikasi CSS scroll-state() - https://www.w3.org/TR/css-conditional-5/#scroll-state-container
- Snapshot tata letak dalam loop peristiwa HTML
- Episode podcast tentang kueri status - https://nerdy.dev/the-css-podcast-on-state-queries
- Artikel lainnya
- https://utilitybend.com/blog/is-the-sticky-thing-stuck-is-the-snappy-item-snapped-a-look-at-state-queries-in-css/
- https://ishadeed.com/article/css-state-queries/
- https://csscade.com/can-you-detect-overflow-with-css/
- https://css-tip.com/overflow-detection/ - mendeteksi dengan animasi yang didorong scroll dengan cara yang dapat diketahui lebih dari sekadar turunan (dengan mengorbankan trik)