یک نمای کلی از نحوه ایجاد یک جزء خردههای نان واکنشگرا و در دسترس برای کاربران جهت پیمایش در سایت شما.
در این پست میخواهم تفکری را درباره روشی برای ساخت اجزای پودر سوخاری به اشتراک بگذارم. نسخه ی نمایشی را امتحان کنید .
اگر ویدیو را ترجیح می دهید، در اینجا یک نسخه YouTube از این پست وجود دارد:
نمای کلی
یک جزء breadcrumbs نشان می دهد که کاربر در کجای سلسله مراتب سایت قرار دارد. این نام از هانسل و گرتل است که خردههای سوخاری را پشت سرشان در جنگلهای تاریک رها کردند و توانستند با ردیابی خردهها به سمت عقب راه خود را به خانه بیابند.
آرد سوخاری های موجود در این پست، پودر سوخاری استاندارد نیستند، آنها مانند آرد سوخاری هستند. آنها با قرار دادن صفحات خواهر و برادر مستقیماً در مسیریابی با یک <select>
، عملکردهای بیشتری را ارائه می دهند که دسترسی چند لایه را ممکن می کند.
سابقه کاربری UX
در ویدئوی نمایشی کامپوننت بالا، دستههای نگهدارنده مکان، ژانرهای بازیهای ویدئویی هستند. این مسیر با پیمایش مسیر زیر ایجاد شده است: home » rpg » indie » on sale
، همانطور که در زیر نشان داده شده است.
این جزء خرده نان باید کاربران را قادر سازد تا از طریق این سلسله مراتب اطلاعات حرکت کنند. پرش از شاخه ها و انتخاب صفحات با سرعت و دقت.
معماری اطلاعات
فکر می کنم در مورد مجموعه ها و آیتم ها مفید است.
مجموعه ها
مجموعه آرایه ای از گزینه ها برای انتخاب است. از صفحه اصلی نمونه اولیه پودر سوخاری این پست، مجموعههای FPS، RPG، خروشان، خزنده سیاهچال، ورزش و پازل هستند.
موارد
یک بازی ویدیویی یک آیتم است، یک مجموعه خاص نیز می تواند یک آیتم باشد اگر مجموعه دیگری را نشان دهد. به عنوان مثال، RPG یک آیتم و یک مجموعه معتبر است. وقتی یک آیتم است، کاربر در آن صفحه مجموعه است. به عنوان مثال، آنها در صفحه RPG هستند، که لیستی از بازی های RPG، از جمله زیر شاخه های اضافی AAA، Indie و Self Published را نشان می دهد.
در اصطلاح علوم کامپیوتر، این مولفه پودر سوخاری نشان دهنده یک آرایه چند بعدی است:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
برنامه یا وب سایت شما دارای معماری اطلاعات سفارشی (IA) خواهد بود که یک آرایه چند بعدی متفاوت ایجاد می کند، اما امیدوارم مفهوم صفحات فرود مجموعه و پیمایش سلسله مراتب بتواند آن را به خرده نان شما نیز تبدیل کند.
طرح بندی ها
نشانه گذاری
اجزای خوب با HTML مناسب شروع می شوند. در این بخش بعدی، انتخابهای نشانهگذاری و نحوه تأثیر آنها بر مؤلفه کلی را پوشش خواهم داد.
طرح تاریک و روشن
<meta name="color-scheme" content="dark light">
متا تگ color-scheme
در قطعه بالا به مرورگر اطلاع می دهد که این صفحه سبک مرورگر روشن و تیره را می خواهد. پودر سوخاری های نمونه شامل هیچ CSS برای این طرح های رنگی نمی شود، و بنابراین پودر سوخاری از رنگ های پیش فرض ارائه شده توسط مرورگر استفاده می کند.
عنصر ناوبری
<nav class="breadcrumbs" role="navigation"></nav>
مناسب است از عنصر <nav>
برای پیمایش سایت استفاده شود، که نقش ARIA ضمنی ناوبری دارد. در آزمایش، متوجه شدم که داشتن ویژگی role
، نحوه تعامل یک صفحهخوان با عنصر را تغییر میدهد، در واقع به عنوان ناوبری اعلام میشود، و بنابراین من آن را انتخاب کردم.
نمادها
هنگامی که یک نماد در یک صفحه تکرار می شود، عنصر <use>
SVG به این معنی است که می توانید یک بار path
تعریف کنید و از آن برای همه نمونه های آیکون استفاده کنید. این از تکرار اطلاعات مسیر مشابه جلوگیری می کند و باعث می شود اسناد بزرگتر و احتمال ناهماهنگی مسیر ایجاد شود.
برای استفاده از این تکنیک، یک عنصر SVG مخفی را به صفحه اضافه کنید و نمادها را در یک عنصر <symbol>
با یک شناسه منحصر به فرد قرار دهید:
<svg style="display: none;">
<symbol id="icon-home">
<title>A home icon</title>
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</symbol>
<symbol id="icon-dropdown-arrow">
<title>A down arrow</title>
<path d="M19 9l-7 7-7-7"/>
</symbol>
</svg>
مرورگر SVG HTML را میخواند، اطلاعات نماد را در حافظه قرار میدهد و با ارجاع بقیه صفحه به ID برای استفادههای بیشتر از نماد ادامه میدهد، مانند این:
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-home" />
</svg>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-dropdown-arrow" />
</svg>
یک بار تعریف کنید، هر چند بار که دوست دارید استفاده کنید، با حداقل تاثیر عملکرد صفحه و یک ظاهر طراحی انعطاف پذیر. توجه aria-hidden="true"
به عنصر SVG اضافه شده است. نمادها برای افرادی که در حال مرور هستند و فقط محتوا را می شنوند مفید نیستند، پنهان کردن آنها از آن کاربران مانع از اضافه کردن نویز غیرضروری می شود.
Split-link .crumb
اینجاست که پودر سوخاری سنتی و آنهایی که در این جزء هستند از هم جدا می شوند. به طور معمول، این فقط یک پیوند <a>
خواهد بود، اما من UX پیمایش را با یک انتخاب پنهان اضافه کرده ام. کلاس .crumb
مسئول چیدمان پیوند و نماد است، در حالی که .crumbicon
مسئول چیدمان نماد و عنصر انتخاب با هم است. من آن را split-link نامیده ام زیرا عملکردهای آن بسیار شبیه به split-button است، اما برای پیمایش صفحه.
<span class="crumb">
<a href="#sub-collection-b">Category B</a>
<span class="crumbicon">
<svg>...</svg>
<select class="disguised-select" title="Navigate to another category">
<option>Category A</option>
<option selected>Category B</option>
<option>Category C</option>
</select>
</span>
</span>
یک پیوند و برخی گزینه ها چیز خاصی نیست، اما عملکرد بیشتری را به یک سوخاری ساده اضافه می کند. افزودن title
به عنصر <select>
برای کاربران صفحهخوان مفید است و اطلاعاتی درباره عملکرد دکمه به آنها میدهد. با این حال، کمک یکسانی را به همه افراد دیگر نیز ارائه میکند، میبینید که جلو و مرکز آن در iPad است. یک ویژگی زمینه دکمه را برای بسیاری از کاربران فراهم می کند.
تزئینات جداکننده
<span class="crumb-separator" aria-hidden="true">→</span>
جداکننده ها اختیاری هستند، اضافه کردن تنها یکی از آنها بسیار عالی است (نمونه سوم را در ویدیوی بالا ببینید). سپس به هر یک از aria-hidden="true"
میدهم، زیرا آنها تزئینی هستند و چیزی نیستند که یک صفحهخوان باید اعلام کند.
ویژگی gap
، که در ادامه پوشش داده می شود، فاصله بین این ها را ساده می کند.
سبک ها
از آنجایی که رنگ از رنگهای سیستمی استفاده میکند، بیشتر شکافها و پشتهها برای سبکها هستند!
جهت و جریان چیدمان
عنصر ناوبری اولیه nav.breadcrumbs
یک ویژگی سفارشی با محدوده را برای استفاده کودکان تنظیم می کند و در غیر این صورت یک طرح بندی افقی تراز شده به صورت عمودی ایجاد می کند. این تضمین می کند که خرده ها، تقسیم کننده ها و نمادها در یک راستا قرار گیرند.
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}
هر .crumb
همچنین یک طرح افقی تراز عمودی با مقداری شکاف ایجاد می کند، اما به ویژه فرزندان پیوند خود را هدف قرار می دهد و سبک white-space: nowrap
. این برای خردههای نان چند کلمهای بسیار مهم است زیرا ما نمیخواهیم آنها چند خطی شوند. بعداً در این پست، سبکهایی را اضافه میکنیم تا سرریز افقی ناشی از این ویژگی white-space
را مدیریت کنیم.
.crumb {
display: inline-flex;
align-items: center;
gap: calc(var(--nav-gap) / 4);
& > a {
white-space: nowrap;
&[aria-current="page"] {
font-weight: bold;
}
}
}
aria-current="page"
اضافه شده است تا پیوند صفحه فعلی را از بقیه متمایز کند. کاربران صفحه خوان نه تنها نشانگر واضحی خواهند داشت که پیوند مربوط به صفحه فعلی است، بلکه به صورت بصری این عنصر را برای کمک به کاربران بینا طراحی کرده ایم تا تجربه کاربری مشابهی داشته باشند.
مؤلفه .crumbicon
از شبکه برای قرار دادن نماد SVG با عنصر <select>
«تقریباً نامرئی» استفاده می کند.
.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
عنصر <select>
آخرین عنصر در DOM است، بنابراین در بالای پشته قرار دارد و تعاملی است. یک سبک opacity: .01
تا عنصر همچنان قابل استفاده باشد و نتیجه یک کادر انتخابی است که کاملاً با شکل نماد مطابقت دارد. این یک راه خوب برای سفارشی کردن ظاهر یک عنصر <select>
در عین حفظ عملکرد داخلی است.
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
سرریز
خرده نان باید بتواند یک مسیر بسیار طولانی را نشان دهد. من طرفدار اجازه دادن به چیزهایی هستم که در صورت لزوم به صورت افقی از صفحه خارج شوند، و احساس کردم این جزء خرده سوخاری به خوبی واجد شرایط است.
.breadcrumbs {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x proximity;
scroll-padding-inline: calc(var(--nav-gap) / 2);
& > .crumb:last-of-type {
scroll-snap-align: end;
}
@supports (-webkit-hyphens:none) { & {
scroll-snap-type: none;
}}
}
سبک های سرریز UX زیر را تنظیم می کنند:
- اسکرول افقی با محفظه اسکرول.
- بالشتک اسکرول افقی.
- یک نقطه ضربه محکم و ناگهانی روی خرده آخر. این به این معنی است که در بارگذاری صفحه اولین بارهای خرده شکسته شده و در معرض دید هستند.
- نقطه ضربه محکم و ناگهانی را از Safari حذف می کند، که با اسکرول افقی و ترکیب افکت ضربه محکم و ناگهانی مشکل دارد.
پرسش های رسانه ای
یکی از تنظیمات ظریف برای درگاههای نمایش کوچکتر مخفی کردن برچسب "Home" است و فقط نماد را باقی میگذارد:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}
قابلیت دسترسی
حرکت
حرکت زیادی در این مولفه وجود ندارد، اما با قرار دادن انتقال در یک بررسی prefers-reduced-motion
، می توانیم از حرکت ناخواسته جلوگیری کنیم.
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
هیچ یک از سبک های دیگر نیازی به تغییر ندارند، جلوه های شناور و فوکوس بدون transition
عالی و معنادار هستند، اما اگر حرکت مناسب باشد، یک انتقال ظریف به تعامل اضافه می کنیم.
جاوا اسکریپت
ابتدا، صرف نظر از نوع روتری که در سایت یا برنامه خود استفاده می کنید، زمانی که کاربر اطلاعات را تغییر می دهد، URL باید به روز شود و کاربر صفحه مناسب را نشان دهد. دوم، برای عادی سازی تجربه کاربر، مطمئن شوید که وقتی کاربران فقط گزینه های <select>
را مرور می کنند، هیچ پیمایش غیرمنتظره ای اتفاق نمی افتد.
دو معیار مهم تجربه کاربر که باید توسط جاوا اسکریپت انجام شود: انتخاب تغییر کرده است و مشتاق <select>
تغییر جلوگیری از شلیک رویداد.
پیشگیری از رویداد مشتاق به دلیل استفاده از عنصر <select>
مورد نیاز است. در Windows Edge و احتمالاً سایر مرورگرها نیز، با مرور گزینهها با صفحهکلید، رویداد changed
انتخابی فعال میشود. به همین دلیل است که من آن را مشتاق نامیدم، زیرا کاربر فقط شبه گزینه را انتخاب کرده است، مانند شناور یا فوکوس، اما انتخاب را با enter
یا click
تأیید نکرده است. رویداد مشتاق باعث میشود این ویژگی تغییر دستهبندی مؤلفه غیرقابل دسترسی باشد، زیرا باز کردن کادر انتخاب و مرور ساده یک مورد، رویداد را فعال میکند و صفحه را تغییر میدهد، قبل از اینکه کاربر آماده شود.
یک رویداد بهتر <select>
تغییر کرده است
const crumbs = document.querySelectorAll('.breadcrumbs select')
const allowedKeys = new Set(['Tab', 'Enter', ' '])
const preventedKeys = new Set(['ArrowUp', 'ArrowDown'])
// watch crumbs for changes,
// ensures it's a full value change, not a user exploring options via keyboard
crumbs.forEach(nav => {
let ignoreChange = false
nav.addEventListener('change', e => {
if (ignoreChange) return
// it's actually changed!
})
nav.addEventListener('keydown', ({ key }) => {
if (preventedKeys.has(key))
ignoreChange = true
else if (allowedKeys.has(key))
ignoreChange = false
})
})
استراتژی این است که رویدادهای پایین صفحه کلید را در هر عنصر <select>
مشاهده کنید و تعیین کنید که آیا کلید فشار داده شده تأیید ناوبری ( Tab
یا Enter
) یا پیمایش فضایی ( ArrowUp
یا ArrowDown
) است. با این تعیین، مؤلفه می تواند تصمیم بگیرد که منتظر بماند یا برود، زمانی که رویداد عنصر <select>
فعال می شود.
نتیجه گیری
حالا که می دانید من چگونه این کار را انجام دادم، چگونه این کار را انجام می دهید‽🙂
بیایید رویکردهایمان را متنوع کنیم و همه راههای ساخت در وب را بیاموزیم. یک نسخه نمایشی ایجاد کنید، پیوندها را برای من توییت کنید ، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم!
ریمیکس های انجمن
- Tux Solbakk به عنوان یک مؤلفه وب: نسخه ی نمایشی و کد