تغییر ترتیب DOM با tabindex
ترتیب برگه های پیش فرض ارائه شده توسط موقعیت DOM عناصر بومی مناسب است، اما مواقعی وجود دارد که می خواهید ترتیب برگه ها را تغییر دهید و حرکت فیزیکی عناصر در HTML همیشه یک راه حل بهینه یا حتی امکان پذیر نیست. . برای این موارد میتوانید از ویژگی HTML tabindex
برای تنظیم صریح موقعیت برگه یک عنصر استفاده کنید.
tabindex
می توان برای هر عنصری اعمال کرد - اگرچه لزوماً برای هر عنصر مفید نیست - و طیفی از مقادیر صحیح را می گیرد. با استفاده از tabindex
، می توانید یک ترتیب صریح برای عناصر صفحه قابل فوکوس مشخص کنید، یک عنصر غیرقابل تمرکز را در ترتیب برگه وارد کنید و عناصر را از ترتیب برگه ها حذف کنید. مثلا:
tabindex="0"
: یک عنصر را به ترتیب برگه طبیعی وارد می کند. عنصر را می توان با فشار دادن کلید Tab
فوکوس کرد و عنصر را می توان با فراخوانی متد focus()
آن فوکوس کرد.
<custom-button tabindex="0">Press Tab to Focus Me!</custom-button>
tabindex="-1"
: یک عنصر را از ترتیب برگه طبیعی حذف می کند، اما همچنان می توان با فراخوانی متد focus()
آن عنصر را فوکوس کرد.
// TODO: DevSite - Code sample removed as it used inline event handlers
// TODO: DevSite - نمونه کد حذف شد زیرا از کنترل کننده رویداد درونی استفاده می کرد
tabindex="5"
: هر tabindex بزرگتر از 0 عنصر را به جلوی ترتیب برگه طبیعی می پرد. اگر چندین عنصر با شاخص تب بزرگتر از 0 وجود داشته باشد، ترتیب برگه ها از کمترین مقداری که بزرگتر از صفر است شروع می شود و به سمت بالا حرکت می کند. استفاده از tabindex بزرگتر از 0 یک ضد الگو در نظر گرفته می شود.
<button>I should be first</button>
<button>And I should be second</button>
<button tabindex="5">But I jumped to the front!</button>
این به ویژه در مورد عناصر غیر ورودی مانند سرصفحه ها، تصاویر یا عنوان مقاله صادق است. افزودن tabindex
به این نوع عناصر نتیجه معکوس دارد. در صورت امکان، بهتر است کد منبع خود را طوری مرتب کنید که دنباله DOM یک ترتیب برگه منطقی را ارائه دهد. اگر tabindex
استفاده میکنید، آن را به کنترلهای تعاملی سفارشی مانند دکمهها، برگهها، کرکرهها و فیلدهای متنی محدود کنید. یعنی عناصری که کاربر ممکن است انتظار داشته باشد که ورودی به آنها ارائه دهد.
نگران نباشید که کاربران صفحهخوان محتوای مهم را از دست میدهند زیرا tabindex
ندارد. حتی اگر محتوا بسیار مهم باشد، مانند یک تصویر، اگر چیزی نیست که کاربر بتواند با آن تعامل داشته باشد، دلیلی برای قابل تمرکز کردن آن وجود ندارد. کاربران صفحهخوان همچنان میتوانند محتوای تصویر را درک کنند تا زمانی که شما از ویژگی alt
پشتیبانی مناسبی ارائه دهید، که به زودی به آن خواهیم پرداخت.
مدیریت تمرکز در سطح صفحه
در اینجا سناریویی وجود دارد که در آن tabindex
نه تنها مفید، بلکه ضروری است. ممکن است در حال ساخت یک صفحه منفرد قوی با بخش های محتوای مختلف باشید که همه آنها به طور همزمان قابل مشاهده نیستند. در این نوع صفحه، کلیک کردن روی پیوند پیمایش ممکن است محتوای قابل مشاهده را بدون انجام بازخوانی صفحه تغییر دهد.
هنگامی که این اتفاق میافتد، احتمالاً ناحیه محتوای انتخابی را شناسایی میکنید، به آن tabindex
-1 میدهید تا به ترتیب برگه طبیعی ظاهر نشود و روش focus
آن را فراخوانی میکنید. این تکنیک که مدیریت تمرکز نامیده می شود، زمینه درک شده کاربر را با محتوای بصری سایت هماهنگ نگه می دارد.
مدیریت تمرکز در اجزاء
مدیریت تمرکز زمانی که چیزی را در صفحه تغییر میدهید مهم است، اما گاهی اوقات لازم است تمرکز را در سطح کنترل مدیریت کنید - برای مثال، اگر در حال ساخت یک جزء سفارشی هستید.
عنصر select
بومی را در نظر بگیرید. میتواند فوکوس اولیه را دریافت کند، اما پس از آن، میتوانید از کلیدهای جهتنما برای نمایش عملکردهای اضافی (گزینههای قابل انتخاب) استفاده کنید. اگر در حال ساختن یک عنصر select
سفارشی بودید، میخواهید همین نوع رفتارها را آشکار کنید تا کاربرانی که عمدتاً به صفحهکلید متکی هستند همچنان بتوانند با کنترل شما تعامل داشته باشند.
<!-- Focus the element using Tab and use the up/down arrow keys to navigate -->
<select>
<option>Aisle seat</option>
<option>Window seat</option>
<option>No preference</option>
</select>
دانستن اینکه کدام رفتارهای صفحه کلید برای پیاده سازی می تواند دشوار باشد، اما یک سند مفید وجود دارد که می توانید به آن مراجعه کنید. راهنمای شیوههای تألیف برنامههای کاربردی اینترنت غنی در دسترس (ARIA) انواع مؤلفهها و انواع عملکردهای صفحهکلید را فهرست میکند. بعداً ARIA را با جزئیات بیشتری پوشش خواهیم داد، اما در حال حاضر اجازه دهید از راهنما استفاده کنیم تا به ما کمک کند تا پشتیبانی از صفحه کلید را به یک جزء جدید اضافه کنیم.
شاید شما در حال کار بر روی برخی از عناصر سفارشی جدید هستید که شبیه به مجموعه ای از دکمه های رادیویی هستند، اما با ظاهر و رفتار منحصر به فرد شما.
<radio-group>
<radio-button>Water</radio-button>
<radio-button>Coffee</radio-button>
<radio-button>Tea</radio-button>
<radio-button>Cola</radio-button>
<radio-button>Ginger Ale</radio-button>
</radio-group>
برای تعیین اینکه آنها به چه نوع پشتیبانی صفحه کلید نیاز دارند، باید راهنمای شیوه های نویسندگی ARIA را بررسی کنید. بخش 2 شامل فهرستی از الگوهای طراحی است، و در آن فهرست یک جدول مشخصه برای گروههای رادیویی وجود دارد، مؤلفه موجود که بیشترین تطابق را با عنصر جدید شما دارد.
همانطور که در جدول می بینید، یکی از رفتارهای رایج صفحه کلید که باید پشتیبانی شود، کلیدهای جهت دار بالا/پایین/چپ/راست است. برای افزودن این رفتار به مؤلفه جدید، از تکنیکی به نام Roving tabindex استفاده خواهیم کرد.
Roving tabindex با تنظیم tabindex
روی -1 برای همه کودکان به جز نمونه فعال فعلی کار می کند.
<radio-group>
<radio-button tabindex="0">Water</radio-button>
<radio-button tabindex="-1">Coffee</radio-button>
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
سپس مؤلفه از شنونده رویداد صفحه کلید برای تعیین اینکه کاربر کدام کلید را فشار می دهد استفاده می کند. هنگامی که این اتفاق می افتد، tabindex
کودکی که قبلاً متمرکز شده بود را روی -1 تنظیم می کند، tabindex
کودک مورد توجه را روی 0 تنظیم می کند و روش تمرکز را روی آن فراخوانی می کند.
<radio-group>
// Assuming the user pressed the down arrow, we'll focus the next available child
<radio-button tabindex="-1">Water</radio-button>
<radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
هنگامی که کاربر به آخرین (یا اولین، بسته به جهتی که فوکوس را حرکت میدهد) میرسد، شما به اطراف میچرخید و دوباره اولین (یا آخرین) فرزند را متمرکز میکنید.
در زیر می توانید نمونه کامل شده را امتحان کنید. عنصر موجود در DevTools را بررسی کنید تا نمایه برگه را از یک رادیو به رادیو دیگر مشاهده کنید.
// TODO: DevSite - نمونه کد حذف شد زیرا از کنترل کننده رویداد درونی استفاده می کرد
می توانید منبع کامل این عنصر را در GitHub مشاهده کنید.
مدال ها و تله های صفحه کلید
گاهی اوقات وقتی تمرکز را مدیریت میکنید، میتوانید در موقعیتی قرار بگیرید که نمیتوانید از آن خارج شوید. یک ویجت تکمیل خودکار را در نظر بگیرید که سعی میکند فوکوس را مدیریت کند و رفتار برگه را ثبت کند، اما از خروج کاربر تا زمانی که کامل نشود، جلوگیری میکند. این تله صفحه کلید نامیده می شود و می تواند برای کاربر بسیار خسته کننده باشد. بخش 2.1.2 چک لیست Web AIM به این موضوع می پردازد و بیان می کند که فوکوس صفحه کلید هرگز نباید در یک عنصر صفحه خاص قفل یا محبوس شود . کاربر باید بتواند تنها با استفاده از صفحه کلید به و از همه عناصر صفحه پیمایش کند.
به طور عجیبی، مواقعی وجود دارد که این رفتار واقعاً مطلوب است، مانند یک پنجره مودال. به طور معمول، زمانی که مدال نمایش داده می شود، نمی خواهید کاربر به محتوای پشت آن دسترسی داشته باشد. ممکن است یک پوشش برای پوشش بصری صفحه اضافه کنید، اما این مانع از حرکت تصادفی فوکوس صفحه کلید به خارج از حالت نمی شود.
در مواردی مانند این، میتوانید یک تله صفحهکلید موقت اجرا کنید تا اطمینان حاصل کنید که فوکوس را فقط در زمانی که مدال نمایش داده میشود به دام میاندازید و سپس هنگامی که مدال بسته است، فوکوس را به آیتم فوکوسشده قبلی بازگردانید.
برخی از پیشنهادات برای آسانتر کردن این کار برای توسعهدهندگان، از جمله عنصر
<dialog>
وجود دارد، اما آنها هنوز از پشتیبانی گسترده مرورگر برخوردار نیستند.این مقاله MDN را برای اطلاعات بیشتر در مورد
<dialog>
و این مثال مودال را برای اطلاعات بیشتر در مورد ویندوزهای مودال ببینید.
یک دیالوگ مودال را در نظر بگیرید که توسط یک div
که حاوی چند عنصر است، و یک div
دیگر که نمایانگر یک پوشش پسزمینه است را در نظر بگیرید. بیایید مراحل اساسی مورد نیاز برای اجرای یک تله صفحه کلید موقت در این شرایط را طی کنیم.
- با استفاده از
document.querySelector
، div های modal و overlay را انتخاب کنید و مراجع آنها را ذخیره کنید. - همانطور که مدال باز می شود، یک مرجع به عنصری که هنگام باز شدن مدال متمرکز شده است ذخیره کنید تا بتوانید فوکوس را به آن عنصر برگردانید.
- از شنونده keydown برای گرفتن کلیدها در حالی که فشار داده می شوند در حالی که مدال باز است استفاده کنید. همچنین میتوانید به یک کلیک روی همپوشانی پسزمینه گوش دهید و اگر کاربر روی آن کلیک کرد، مدال را ببندید.
- در مرحله بعد، مجموعه ای از عناصر قابل تمرکز را در مودال دریافت کنید. اولین و آخرین عناصر قابل فوکوس به عنوان "نگهبان" عمل می کنند تا به شما اطلاع دهند که چه زمانی فوکوس را به جلو یا عقب برگردانید تا در داخل مودال بمانید.
- پنجره مودال را نمایش دهید و اولین عنصر قابل فوکوس را فوکوس کنید.
- همانطور که کاربر
Tab
یاShift+Tab
را فشار می دهد، فوکوس را به جلو یا عقب ببرید و در صورت لزوم در آخرین یا اولین عناصر حلقه بزنید. - اگر کاربر
Esc
را فشار داد، مدال را ببندید. این بسیار مفید است زیرا به کاربر این امکان را می دهد که بدون جستجوی دکمه بسته خاص، مودال را ببندد و حتی برای کاربرانی که از ماوس استفاده می کنند نیز سود می برد. - وقتی مدال بسته شد، آن و پوشش پسزمینه را پنهان کنید و فوکوس را به عنصری که قبلاً فوکوس شده بود ذخیره کنید.
این روش به شما یک پنجره مودال قابل استفاده و غیر خسته کننده می دهد که همه می توانند به طور موثر از آن استفاده کنند.
برای جزئیات بیشتر، می توانید این نمونه کد را بررسی کنید و یک نمونه زنده را از یک صفحه تکمیل شده مشاهده کنید.