نشانگر پیشرفت پیمایش یک الگوی میانای کاربر رایج است که پیشرفت کاربر را در یک سند یا ظرف قابلپیمایش بهصورت بصری نشان میدهد. با پیمایش کاربر، یک عنصر دیداری بهروز میشود تا موقعیت او را نشان دهد و حس واضح و شهودی از اینکه چقدر محتوا مشاهده شده و چقدر باقی مانده است ارائه دهد.
نحوه پیادهسازی
برای ایجاد نشانگر پیشرفت پیمایش، به دو چیز نیاز دارید:
- عنصری که بهعنوان نوار پیشرفت عمل میکند. این عنصر معمولاً
position: fixedیاposition: absoluteاست تا وقتی کاربر پیمایش میکند در دید باقی بماند. - پویانماییای که به موقعیت پیمایش پیوند داده شده است.
از این طریق میتوانید به این هدف برسید:
- ابتدا، یک عنصر HTML ایجاد کنید که بهعنوان نوار پیشرفت شما عمل کند. این عنصر را میتوانید مطابق میل خودتان سبکبندی کنید.
- سپس، در CSS خود، یک پویانمایی
@keyframesتعریف کنید که نوار پیشرفت را مقیاسبندی کند. یک رویکرد رایج، مقیاسبندی عنصر ازscaleX(0)بهscaleX(1)است. - درنهایت، این پویانمایی را روی عنصر نوار پیشرفت اعمال کنید و
animation-timelineآن را روی scroll-timeline تنظیم کنید. این به مرورگر میگوید که پیشرفت پویانمایی را براساس موقعیت پیمایش نزدیکترین پیمایشگر اجدادی هدایت کند.
کد نمونه
این کد عنصر #progress را در پیمایش بااستفاده از یک خط زمان پیمایش ناشناس که توسط تابع scroll() ایجاد شده است، رشد میدهد.
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: scroll();
}
}
}
بهدلیل مکان آن در DOM، تابع scroll() نزدیکترین پیمایشگر جد خود را در جهت block ردیابی میکند که در اینجا پیمایشگر ریشه است.
<body>
<!-- MANDATORY: Purely decorative visual scroll progress bars MUST set aria-hidden="true" to remove the empty element from the assistive technology reading tree -->
<div id="progress" aria-hidden="true"></div>
</body>
این کد عنصر #progress را در پیمایش بااستفاده از یک خط زمان پیمایش نامگذاریشده که توسط ویژگی scroll-timeline ایجاد شده است، رشد میدهد.
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
:root {
scroll-timeline: --tl block;
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: --tl;
}
}
}
روالهای مطلوب
هنگام استفاده از پویانماییهای پیمایشمحور، مهم است که چند روال مطلوب را دنبال کنید تا تجربهای روان و دسترسپذیر را تضمین کنید:
- باید تشخیص ویژگی را اضافه کنید: همه مرورگرها از پویانماییهای پیمایشمحور پشتیبانی نمیکنند. از
@supports (animation-timeline: scroll())برای بررسی پشتیبانی و ارائه بازگشت به روش پیشفرض برای مرورگرهایی که از آن پشتیبانی نمیکنند استفاده کنید.- از بسته
scroll-timeline-polyfillبرای راهبرد جایگزین استفاده نکنید زیرا ویژگیهای آن کامل نیست و مشکلات شناختهشده زیادی دارد. - اگر پویانمایی فقط تزئینی درنظر گرفته میشود، «ارتقای پیشرو» را انتخاب کنید و گزینه جایگزین ارائه ندهید.
- از بسته
- باید عناصر صرفاً تزئینی را از جریانهای خواندن فناوری کمکی بردارید:
aria-hidden="true"را برای نشانگرهای پیمایش صرفاً دیداری اعمال کنید تا مطمئن شوید صفحهخوانها با گرههای خالی و بینام مواجه نمیشوند. - باید به اولویتهای کاربر احترام بگذارید: برخیاز کاربران ترجیح میدهند حرکت کمتری در وب داشته باشند. از پُرسمان رسانه
prefers-reduced-motionبرای غیرفعال کردن یا کاهش پویانماییها برای این کاربران استفاده کنید. - باید سعی کنید فقط داراییهای CSS کارا را پویانمایی کنید: برای داشتن روانترین پویانماییها، فقط داراییهایی را پویانمایی کنید که رشته ترکیبکننده مرورگر میتواند آنها را مدیریت کند، مثل
transformوopacity. پویانمایی کردن ویژگیهای دیگر مثلwidthیاheightمیتواند به مشکلات عملکردی منجر شود. - باید از ترتیب صحیح اعلام استفاده کنید: هنگام استفاده از ویژگی خلاصه
animation،animation-timelineرا بعداز آن اعلام کنید تا از بازنشانی خط زمان توسط خلاصه جلوگیری شود.
هنگام استفاده از تابع scroll() برای ایجاد پویانمایی پیمایشمحور:
- اختیاری درباره پیمایشگر صریح باشید: وقتی نزدیکترین پیمایشگر جد را هدف قرار نمیدهید، درباره اینکه میخواهید از کدام پیمایشگر با
scroll(root)یاscroll(self)استفاده کنید صریح باشید.- وقتی
root،nearest، یاselfکافی نیستند، از scroll-timeline نامگذاریشده استفاده کنید.
- وقتی
- اختیاری بهطور صریح محور موردنظر برای ردیابی را مشخص کنید: وقتی محور پیشفرض
blockرا هدف قرار نمیدهید (مثلاً در پیمایشگر افقی)، بهطور صریح مشخص کنید که کدام محور باید باscroll(block)یاscroll(inline)ردیابی شود.
هنگام استفاده از ویژگی scroll-timeline برای ایجاد پویانمایی پیمایشمحور:
- باید از CSS
<dashed-ident>برای نام استفاده کنید. - اختیاری محور موردنظر برای ردیابی را بهطور صریح مشخص کنید: وقتی محور پیشفرض
blockرا هدف قرار نمیدهید (مثلاً در پیمایشگر افقی)، بهطور صریح مشخص کنید که کدام محور باscroll-timeline-axisردیابی شود. - باید مطمئن شوید که دامنه جستجو کار میکند: وقتی عنصری که
scroll-timelineرا اعلام میکند، جد درخت مسطح عنصر پویانماییشده نیست، بااستفاده ازtimeline-scopeدر جد مشترک، نمایان بودن نامscroll-timelineرا بالا ببرید.
راهبردهای جایگزین
برای مرورگرهایی که از پویانماییهای پیمایشمحور پشتیبانی نمیکنند، میتوانید از یک جایگزین برای بازآفرینی جلوههای دیداری استفاده کنید. جایگزینها معمولاً با شنونده پیمایش (برای جلوههای ScrollTimeline) یا IntersectionObserver API (برای جلوههای ViewTimeline) ساخته میشوند.
در مرورگرهایی که پشتیبانی داخلی از پویانماییهای پیمایشمحور دارند، همیشه از پیادهسازی CSS بومی استفاده کنید زیرا عملکرد بهتری دارند.
توجه داشته باشید که همه جلوهها را نمیتوان بااستفاده از رویکرد جایگزین بازآفرینی کرد.
بهطور خاص برای این مورد استفاده، دستورگان زیر برای مرورگرهایی که از پویانماییهای پیمایشمحور پشتیبانی نمیکنند، جایگزین را اعمال میکند. این برنامه از یک شنونده پیمایش برای ردیابی موقعیت پیمایش عنصر ریشه استفاده میکند و ویژگی transform نوار پیشرفت را براساس آن بهروز میکند.
<script>
if (!CSS.supports('animation-timeline', 'scroll()')) {
const progress = document.querySelector('#progress');
window.addEventListener('scroll', () => {
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
const scrolled = window.scrollY;
const progressPercentage = (scrolled / scrollable);
progress.style.transform = `scaleX(${progressPercentage})`;
});
}
</script>