ARIA: وقتی HTML بهتنهایی کافی نیست
در درسهای قبل این فصل، بارها از ویژگیهایی مثل role، aria-label، aria-describedby و aria-live استفاده کردیم، بدون توضیح کامل اینکه اینها از کجا میآیند. در این درس، بهطور مستقیم به ARIA میپردازیم: چیست، چه زمانی لازم است، و مهمتر از همه، چه زمانی نباید از آن استفاده کرد.
ARIA چیست
ARIA (مخفف Accessible Rich Internet Applications) مجموعهای از ویژگیهای HTML است که اطلاعات اضافهای درباره نقش، وضعیت و رابطه عناصر، به ابزارهای کمکی مثل صفحهخوان میدهد؛ اطلاعاتی که گاهی خود تگهای معمولی HTML بهتنهایی نمیتوانند بیان کنند.
قانون اول و مهمترین قانون ARIA
مستندات رسمی ARIA یک قاعده صریح دارد: اگر یک عنصر HTML معنایی (مثل button) از قبل همان رفتار و معنایی را دارد که نیاز دارید، از همان استفاده کنید؛ ARIA را فقط برای مواردی به کار ببرید که HTML استاندارد، راهحلی برایشان ندارد. اضافه کردن role="button" به یک button واقعی، نهتنها بیفایده، بلکه گاهی باعث رفتار متناقض میشود.
// غیرضروری و اشتباه
<button role="button">ارسال</button>
// درست: همینقدر کافی است
<button>ارسال</button>سه دسته اصلی ویژگیهای ARIA
ویژگیهای ARIA معمولاً در سه گروه قرار میگیرند:
- Roles: نقش یک عنصر را مشخص میکنند؛ مثلاً
role="dialog"که در درس قبل برای Modal دیدیم. - Properties: ویژگیهای نسبتاً ثابت یک عنصر را توصیف میکنند؛ مثل
aria-labelکه در درس دوم دیدیم. - States: وضعیت فعلی و قابلتغییر یک عنصر را نشان میدهند؛ مثل
aria-expandedیاaria-checked.
یک مثال از State: آکاردئون با aria-expanded
function AccordionItem({ title, children }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button
aria-expanded={isOpen}
onClick={() => setIsOpen(!isOpen)}
>
{title}
</button>
{isOpen && <div>{children}</div>}
</div>
);
}
اینجا aria-expanded مستقیم به همان State که باعث نمایش یا پنهان شدن محتوا میشود متصل است؛ همانطور که در فصل اول با Conditional Rendering دیدیم، این دو (نمایش بصری و اعلام وضعیت) باید همیشه از یک منبع واحد بیایند تا هماهنگ بمانند.
چرا این اتصال در React طبیعی است
نکته جالب این است که چون ARIA فقط چند ویژگی اضافه روی JSX است، دقیقاً مثل هر Prop دیگری با State کنترل میشود؛ نیازی به ابزار یا الگوی خاصی نیست. همان قوانینی که در فصل اول درباره Conditional Rendering و Expression داخل JSX دیدیم، بدون تغییر، برای ARIA هم کار میکنند.
خطری که زیاد استفاده کردن ARIA دارد
ARIA نادرست، میتواند وضعیت را بدتر از نبودنش کند؛ مثلاً اگر aria-expanded="true" روی عنصری بماند که واقعاً دیگر باز نیست، صفحهخوان اطلاعات اشتباه میدهد. به همین دلیل، یک اصل رایج در جامعه دسترسپذیری این است: «ARIA بد، بدتر از نبود ARIA است»؛ باید فقط جایی اضافه شود که واقعاً لازم و درست پیادهسازی شده باشد.
مثال قابل اجرا
import { useState } from "react";
function AccordionItem({ title, children }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button aria-expanded={isOpen} onClick={() => setIsOpen(!isOpen)}>
{title} {isOpen ? "▲" : "▼"}
</button>
{isOpen && <div style={{ padding: "8px" }}>{children}</div>}
</div>
);
}
function App() {
return (
<AccordionItem title="جزئیات بیشتر">
<p>این محتوای پنهانشده آکاردئون است.</p>
</AccordionItem>
);
}جمعبندی
ARIA شامل Roles، Properties و States است که اطلاعاتی فراتر از توانایی HTML استاندارد به ابزارهای کمکی میدهند؛ اما باید فقط وقتی استفاده شود که یک تگ معنایی موجود، همان نقش را پوشش نمیدهد. State های ARIA مثل aria-expanded باید همیشه مستقیم به همان State واقعی React متصل باشند، نه یک مقدار ثابت یا جدا. در درس بعدی، این اصول را در طراحی کامپوننتهای کامل و قابلدسترس به کار میبریم.
