نمای کلی
نشانههای دیداری، مانند سایهها یا گرادیانها، به کاربران کمک میکنند تا متوجه شوند که میتوانند برای دیدن محتوای بیشتر پیمایش کنند. این راهنما نشان میدهد که چگونه این نکات را بااستفاده از CSS container-scroll-state-queries بسازید، که امکان سبکدهی به عناصر را براساس وضعیت پیمایشپذیر ظرف آنها بدون تکیه بر شنوندگان یا ناظران پیمایش جاوا اسکریپت فراهم میکند.
پیادهسازی
۱. ایجاد محتوی پیمایش
محتوای پیمایش باید بهعنوان محتوای پُرسمان حالت پیمایش اعلام شود.
.scroller {
overflow-y: auto;
/* Establish this element as a scroll-state query container */
container-type: scroll-state;
position: relative;
}
۲. سبک نشانگرها
عناصر نشانگر (مانند سایهها، گرادیانها، یا پیکانها) را داخل محفظه قرار دهید و به آنها سبک دهید. بهطور پیشفرض، نباید قابلمشاهده باشند. وقتی نشان داده میشوند، نباید تعاملی باشند، با تنظیم pointer-events: none.
.indicator-top, .indicator-bottom {
position: sticky;
left: 0;
right: 0;
height: 20px;
opacity: 0;
transition: opacity 0.2s;
pointer-events: none; /* Let clicks pass through */
}
.indicator-top {
top: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0.2), transparent); /* Example: Shadow */
}
.indicator-bottom {
bottom: 0;
background: linear-gradient(to top, rgba(0,0,0,0.2), transparent); /* Example: Shadow */
}
۳. پرسوجو کردن وضعیت پیمایش
از قانون @container با تابع scroll-state استفاده کنید. بررسی کنید که آیا محفظه برای نمایش نشانگر مربوطه به بالا یا پایین پیمایشپذیر است یا نه.
/* Show top indicator when the user can scroll up */
@container scroll-state(scrollable: top) {
.indicator-top {
opacity: 1;
}
}
/* Show bottom indicator when the user can scroll down */
@container scroll-state(scrollable: bottom) {
.indicator-bottom {
opacity: 1;
}
}
راهبردهای جایگزین
بازگشت پایه
اگر از این ویژگی پشتیبانی نشود، نشانگرها نامرئی باقی میمانند. ازآنجاییکه اینها نکته هستند و برای عملکرد ضروری نیستند، حذف آنها در مرورگرهای پشتیبانینشده قابلقبول است.
بازگشت پیشرفته (ناظر تقاطع)
اگر به راهنمایی نیاز دارید، از IntersectionObserver برای تغییر کلاسها استفاده کنید، وقتی عناصر نگهبان در بالا و پایین پیمایشگر به داخل و خارج از درگاه پیمایش حرکت میکنند.
<!-- Sentinel elements placed at the ends of the scroller -->
<div class="sentinel-top"></div>
<!-- Content goes here -->
<div class="sentinel-bottom"></div>
/* Marker styling to ensure it does not affect layout */
.sentinel-top, .sentinel-bottom {
height: 0;
width: 0;
visibility: hidden;
}
.scroller.scrolled-down .indicator-top {
opacity: 1;
}
.scroller.can-scroll-down .indicator-bottom {
opacity: 1;
}
if (!CSS.supports('container-type', 'scroll-state')) {
const topSentinel = document.querySelector('.sentinel-top');
const bottomSentinel = document.querySelector('.sentinel-bottom');
const scroller = document.querySelector('.scroller');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.target === topSentinel) {
// If top sentinel is not intersecting, we have scrolled down
scroller.classList.toggle('scrolled-down', !entry.isIntersecting);
}
if (entry.target === bottomSentinel) {
// If bottom sentinel is intersecting, we reached the bottom
scroller.classList.toggle('can-scroll-down', !entry.isIntersecting);
}
});
}, { root: scroller });
observer.observe(topSentinel);
observer.observe(bottomSentinel);
}