الگوهای «تند کشیدن برای آشکار کردن» به کاربران اجازه میدهد ردیف پیشزمینه یا قاب محتوا را بهصورت افقی بلغزانند تا واسط کاربر پنهان را نمایان کنند—مانند دکمههای کنش بافتاری (سنجاق کردن، بیصدا کردن، بایگانی کردن، حذف کردن) یا منو کناری ثانویه—بدون اینکه هیچ کنشی بهطور خودکار فعال شود. بهجای انجام کنش درطول تند کشیدن، محفظه بهسرعت باز میشود تا کنترلهای تعاملی را نشان دهد که کاربر میتواند آنها را بررسی و فعال کند، یا برای بستن آنها تند به عقب بکشد.
برای اشاره تند کشیدن تمامعرض که بلافاصله موردی را پساز عبور از آستانه اعمال و رد میکند، به تند کشیدن برای برداشتن مراجعه کنید. برای آشکار کردن سرصفحه پنهان در بالای محفظه پیمایش عمودی، کشیدن برای آشکار کردن را ببینید.
نحوه پیادهسازی
چه دکمههای کنش را در یک مورد فهرست نشان دهید یا در یک منو کناری کنار یک قاب پیمایشپذیر، سازوکارها یکسان هستند: محتوای پیشزمینه و پانل پنهان را درون یک ظرف پیمایش افقی بیرونی که با CSS Scroll Snap (scroll-snap-type: x mandatory) و overscroll-behavior: chain پیکربندی شده است، بپیچید. موتور پیمایش بومی مرورگر، تکانه، چسبیدن، پیمایش تمرکز صفحهکلید، و زنجیرهسازی پیمایش را بدون شنوندگان اشاره جاوا اسکریپت مدیریت میکند.
مرحله ۱: نشانهگذاری پوشاننده تند کشیدن، محتوا، و پانل آشکارشده
ابتدا محتوای پیشزمینه و سپس کنترلهای آشکارشده (دکمههای کنش یا منو کناری) را داخل محفظه پیمایش .SwipeReveal قرار دهید. چون محتوا در ترتیب DOM اول است، محفظه پیمایش بهطور طبیعی در افست پیمایش 0 شروع میشود و پانل در خارج از صفحه در سمت راست پنهان است.
<!-- Example A: List item with revealable action buttons -->
<div class="SwipeReveal">
<div class="SwipeReveal-content">
<strong>Design review notes</strong>
<p>Updated component specs for the Q3 release.</p>
</div>
<div class="SwipeReveal-panel" role="group" aria-label="Item actions">
<button type="button">Pin</button>
<button type="button">Archive</button>
<button type="button">Delete</button>
</div>
</div>
<!-- Example B: Scrollable content pane with a revealable side menu -->
<div class="SwipeReveal" role="region" aria-label="Document preview with swipeable side menu">
<div class="SwipeReveal-content is-scrollable" tabindex="0">
<h2>Article Preview</h2>
<p>Scroll vertically through this pane, or swipe left to reveal the side menu...</p>
</div>
<nav class="SwipeReveal-panel" aria-label="Contextual menu">
<a href="#share">Share</a>
<a href="#bookmark">Bookmark</a>
<a href="#export">Export PDF</a>
</nav>
</div>
مرحله ۲: پیکربندی محفظه چفت کردن افقی و overscroll-behavior: chain
وقتی عنصری را صرفاً برای ایجاد جلوه «تند کشیدن برای آشکار کردن» در یک محفظه پیمایش بیرونی قرار میدهید، آن محفظه بیرونی به یک پیمایشگر واسطه در داخل سند (یا محفظه پیمایش والد دیگر) تبدیل میشود.
چهار کلیدواژه overscroll-behavior بهطور مستقل کنترل میکنند که آیا پیمایش اضافی به محفظه پیمایش بالادست منتشر میشود (زنجیرهسازی پیمایش) و آیا محفظه امکانات پیمایش اضافی محلی مانند کشش کشسان یا درخشش لبه را نمایش میدهد (اثر مرز محلی):
| مقدار | زنجیره پیمایش (به والد منتقل میشود) | جلوه مرز محلی (نوار لاستیکی / درخشش) | نقش در «تند کشیدن برای آشکار کردن» |
|---|---|---|---|
auto |
بله | بله | رفتار پیشفرض؛ این را در پیمایشگرهای محتوای داخلی که بازخورد پرش عادی موردنظر است نگه دارید، اما در پوشاننده تند کشیدن بیرونی که باعث پرش منو میشود از آن اجتناب کنید |
chain |
بله | نه | از آن در پیمایشگر بیرونی .SwipeReveal استفاده کنید تا پیمایش اضافی به پیمایشگر والد (مانند سند) زنجیر شود، بدون اینکه منو یا نوار کنش جهش کند |
contain |
نه | بله | پیمایش را در داخل محفظه بهدام میاندازد درحالیکه همچنان بهصورت محلی جهش میکند |
none |
نه | نه | هم پرش محلی و هم زنجیره پیمایش به اجداد را مسدود میکند |
.SwipeReveal را به جدول دو ستونی (grid-template-columns: 100% max-content) تبدیل کنید که در آن .SwipeReveal-content به start و .SwipeReveal-panel به end میچسبد:
.SwipeReveal {
/* Column 1: full-width content. Column 2: auto-sized actions or side menu. */
display: grid;
grid-template-columns: 100% max-content;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
/* Prevent the swipe wrapper and revealed panel from bouncing locally while
still chaining excess scroll into the parent scroller (the document). */
overscroll-behavior: chain;
}
@media (prefers-reduced-motion: no-preference) {
.SwipeReveal {
scroll-behavior: smooth;
}
}
.SwipeReveal-content {
scroll-snap-align: start;
scroll-initial-target: nearest;
background: Canvas;
}
.SwipeReveal-content:focus-visible {
outline: auto;
outline-offset: -2px;
}
.SwipeReveal-content.is-scrollable {
block-size: 20rem;
overflow: auto;
/* Keeps default `overscroll-behavior: auto` so the content pane retains
its normal bounce effect while chaining horizontal swipes to `.SwipeReveal`. */
}
.SwipeReveal-panel {
/* Snapping a trailing panel to `end` (or a leading panel to `start`) brings
all controls fully into view while keeping the adjacent edge of the content visible. */
scroll-snap-align: end;
display: flex;
&:first-child {
scroll-snap-align: start;
}
}
اگر میخواهید کنترلها را در سمت چپ (
inline-start) بااستفاده از سه ستون (grid-template-columns: max-content 100% max-content) یا دو ستون (max-content 100%) نیز آشکار کنید،.SwipeReveal-panelپیشرو را قبلاز.SwipeReveal-contentقرار دهید. چون.SwipeReveal-contentدارایscroll-initial-target: nearestاست، محفظه پیمایش در ابتدا روی ستون محتوا قرار میگیرد نه پانل پیشرو.
مرحله ۳: برگرداندن قابهای محتوای قابلتمرکز به نمای تمرکز صفحهکلید
چون دکمهها یا پیوندهای داخل .SwipeReveal-panel در حالت استراحت خارج از صفحه هستند، زدن کلید Tab برای رفتن به آنها با صفحهکلید بهطور خودکار .SwipeReveal را پیمایش میکند تا کنترل متمرکزشده را نشان دهد. بااینحال، چون .SwipeReveal-content 100% از عرض ظرف بیرونی را دربرمیگیرد، بیشتر آن حتی وقتی پانل کناری باز است درون درگاه پیمایش باقی میماند—بنابراین، فشار دادن Shift+Tab برای برگرداندن تمرکز به .SwipeReveal-content (یا به عنصر قابلتمرکز درون آن) بهطور خودکار قطعه را به 0 پیمایش نمیکند.
به focusin در .SwipeReveal-content گوش دهید و event.target.matches(':focus-visible') را بررسی کنید تا تمرکز صفحهکلید روی قاب یا هر فرزند .SwipeReveal-content بدون تداخل با کلیکهای اشارهگر یا کشیدنهای لمسی به شروع برگردد:
for (const content of document.querySelectorAll('.SwipeReveal-content')) {
content.addEventListener('focusin', (event) => {
if (event.target.matches(':focus-visible')) {
content.scrollIntoView({
block: 'nearest',
inline: 'start',
});
}
});
}
روالهای مطلوب و تلهها
- باید از
scroll-snap-type: x mandatoryبهجایproximityاستفاده کنید. باproximity، با تند کشیدن ملایم میتوانید دکمههای کنش یا منو کناری را در حالت استراحت تاحدی نمایان کنید. - باید
overscroll-behavior: chainرا روی پیمایشگر بیرونی افقی «تند کشیدن برای آشکار کردن» (.SwipeReveal) تنظیم کنید تا پیمایش بتواند بدون پرش منو یا نوار کنش آشکارشده به پیمایشگر والد زنجیر شود. - باید
overscroll-behavior: auto(پیشفرض) را در قابهای محتوای پیمایشی داخلی (.SwipeReveal-content.is-scrollable) که میخواهید بازخورد پرش عادی در آنها اتفاق بیفتد، باقی بگذارید و درعینحال تند کشیدنهای افقی را به پیمایشگر تند کشیدن خارجی زنجیر کنید. - باید کنشهای آشکارشده و موارد منو کناری را بهعنوان کنترلهای DOM واقعی قابلتمرکز (
<button>،<a>) پیادهسازی کنید. وقتی.SwipeReveal-contentقابلتمرکز است یا حاوی کنترلهای قابلتمرکز است، یک شنوندهfocusinرا باevent.target.matches(':focus-visible')جفت کنید تاscrollIntoView({ block: 'nearest', inline: 'start' })را فراخوانی کند تا با زدن کلید جهش برای برگشتن به صفحه محتوا، پانل کناری بدون تأثیر گذاشتن بر تعاملات اشارهگر بسته شود. - نباید رویدادهای
wheel،touchmove، یاpointermoveرا در جاوا اسکریپت رهگیری کنید تا محتوا را بهصورت دستی ترجمه کنید یا زنجیره پیمایش را شبیهسازی کنید. رهگیری اشاره رشته اصلی، پیمایش مبتنی بر ترکیبکننده را مسدود میکند، تکانه پیمایش بومی را میشکند، و پاسخگویی را کاهش میدهد.
بازگشت
وقتی محفظه .SwipeReveal، .SwipeReveal-panel را در سمت چپ (inline-start) قبلاز .SwipeReveal-content قرار میدهد، مرورگرهایی که از scroll-initial-target: nearest پشتیبانی نمیکنند در ابتدا در جابهجایی پیمایش 0 با پانل پیشتاز نمایانشده ارائه میشوند.
If your Baseline target does not support scroll-initial-target, detect support with CSS.supports('scroll-initial-target', 'nearest') and call scrollTo() with behavior: 'instant' on load so containers with a leading panel jump straight to .SwipeReveal-content without scrolling the page:
ارتقای پیشرو
با overscroll-behavior: chain و scrollbar-width: none بهعنوان ارتقای پیشرو بدون بازگشت جاوا اسکریپت رفتار کنید:
- جایگزین آبشاری CSS خودکار: مقدار اولیه
overscroll-behaviorبرابر باautoاست. مرورگرهایی که هنوز کلیدواژهchainرا تشخیص نمیدهند،overscroll-behavior: chainرا در زمان تجزیه نادیده میگیرند وautoرا حفظ میکنند. ازآنجاییکهautoازقبل امکان زنجیرهسازی پیمایش به محفظههای پیمایش اجدادی را فراهم میکند، هم اشاره تند کشیدن برای آشکار کردن و هم زنجیرهسازی پیمایش به والد در همه مرورگرها بهطور پیشفرض کار میکنند؛ مرورگرهای پشتیبانیکننده بهسادگی پرش ناخواسته نوار لاستیکی را در پوشش تند کشیدن بیرونی سرکوب میکنند. - لغو کردن
containیاnone: اگر برگه سبک نگارش پایه یا کلاس ابزارoverscroll-behavior: containیاnoneرا تنظیم میکند،overscroll-behavior: autoرا بلافاصله قبلازoverscroll-behavior: chainاعلام کنید تا مرورگرهایی که هنوز ازchainپشتیبانی نمیکنند همچنان پیمایش را بهجای بهتله انداختن به والد زنجیر کنند. - پنهان کردن نوار پیمایش (
scrollbar-width: none): پنهان کردن نوار پیمایش افقی صرفاً جنبه ظاهری دارد؛ اگر موتور قدیمیتریscrollbar-width: noneرا نادیده بگیرد، محفظه «تند کشیدن برای آشکار کردن» با نوار پیمایش استاندارد کاملاً کاربردی باقی میماند.