نشانگر فوکوس؛ چیزی که هیچ‌وقت نباید فداش کنید

تو فصل ۲۲ چند بار به :focus-visible اشاره کردیم، ولی همیشه در حاشیه‌ی یه موضوع دیگه (مثل استایل‌دهی فرم‌ها). حالا با شروع یه فصل جدید که کاملاً به Accessibility اختصاص داره، وقتشه یه بار جدی‌تر و مستقل به focus indicator بپردازیم؛ چون این یکی از معدود جاهایی تو CSS هست که تصمیم‌های ظاهری شما می‌تونه مستقیماً تعیین کنه یه بخش از کاربرها اصلاً بتونن از سایت شما استفاده کنن یا نه.

چرا focus indicator این‌قدر حیاتیه؟

کاربرهایی که با کیبورد navigate می‌کنن (چه به‌خاطر ناتوانی حرکتی، چه به‌خاطر ترجیح شخصی، چه به‌خاطر خراب بودن موس)، تنها راهشون برای فهمیدن «الان کجای صفحه هستم» همین نشانگر فوکوسه. بدون اون، فشار دادن Tab عملاً کوره؛ کاربر نمی‌دونه الان روی کدوم لینک، دکمه یا فیلده و چه اتفاقی میفته اگه Enter بزنه.

outline: none بدون جایگزین؛ یکی از رایج‌ترین اشتباهات وب

تو درس‌های قبل هم اشاره کردیم، ولی اینجا با جزئیات بیشتر مرورش می‌کنیم. خیلی از توسعه‌دهنده‌ها، چون outline پیش‌فرض مرورگر رو زشت می‌دونن، این‌جوری می‌نویسن:

/* فاجعه از نظر accessibility */
* {
  outline: none;
}

این کد، فوکوس رو از کل صفحه برای همه‌ی کاربرهای کیبورد نامرئی می‌کنه. اگه واقعاً ظاهر outline پیش‌فرض رو دوست ندارید، همیشه باید یه جایگزین بذارید، نه این‌که کامل حذفش کنید:

*:focus {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

outline-offset: فاصله‌ی بین المنت و نشانگر

یه نکته‌ی ظریف که خیلی وقت‌ها نادیده گرفته می‌شه، outline-offset هست. outline برخلاف border، فضایی از layout اشغال نمی‌کنه (چون بیرون از box model محاسبه می‌شه)، پس می‌شه یه فاصله‌ی کوچیک بینش و خود المنت گذاشت تا خواناتر باشه:

.btn:focus-visible {
  outline: 2px solid #3b82f6;
  outline-offset: 3px;
}

بدون این فاصله، خصوصاً روی المنت‌هایی با border-radius یا پس‌زمینه‌ی تیره، outline ممکنه بچسبه به لبه‌ی المنت و کمتر قابل تشخیص باشه.

چرا outline بهتر از box-shadow برای فوکوسه؟ (و کِی برعکسش درسته)

بعضی طراح‌ها به‌جای outline، از box-shadow برای نشون دادن فوکوس استفاده می‌کنن:

.btn:focus-visible {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
}

این روش یه مزیت داره: با border-radius المنت هماهنگ می‌مونه و ظاهر نرم‌تری داره، در حالی که outline معمولاً یه مستطیل کامل دور المنت می‌کشه حتی اگه خود المنت گرد باشه (چند مرورگر جدید این رو بهتر مدیریت می‌کنن، ولی نه همه). اما یه نکته‌ی مهم: box-shadow برخلاف outline، تو حالت forced-colors (حالت کنتراست بالای ویندوز) به‌طور خودکار توسط سیستم‌عامل قابل‌شناسایی و جایگزین نیست. یعنی اگه فقط از box-shadow استفاده کنید، کاربرهایی که از حالت کنتراست بالا استفاده می‌کنن، ممکنه هیچ نشانه‌ی فوکوسی نبینن. برای امنیت بیشتر، بهترین روش ترکیب هر دوئه:

.btn:focus-visible {
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px white, 0 0 0 4px #3b82f6;
}

کنتراست کافی برای outline

مثل هر عنصر بصری دیگه‌ای، رنگ outline هم باید نسبت به پس‌زمینه‌ی اطرافش کنتراست کافی داشته باشه. طبق راهنمای WCAG، عناصر غیرمتنی مثل نشانگر فوکوس باید حداقل نسبت کنتراست ۳ به ۱ نسبت به رنگ‌های مجاورشون داشته باشن:

/* بد: آبی روشن رو پس‌زمینه‌ی آبی، کنتراست ناکافی */
.btn-primary {
  background: #60a5fa;
}
.btn-primary:focus-visible {
  outline-color: #93c5fd;
}

/* بهتر: outline با کنتراست بالا، مستقل از رنگ خود دکمه */
.btn-primary:focus-visible {
  outline: 2px solid #1e3a8a;
  outline-offset: 2px;
}

سایز و ضخامت نشانگر

یه outline خیلی نازک (مثلاً ۱ پیکسل) ممکنه برای کاربرهایی با دید ضعیف به‌سختی دیده بشه. توصیه‌ی رایج، حداقل 2px ضخامته:

:focus-visible {
  outline-width: 2px;
  outline-style: solid;
}

استفاده از focus-visible به‌جای focus برای تجربه‌ی بهتر ماوس و کیبورد هردو

همون‌طور که قبلاً دیدیم، فرق اصلی اینه که :focus با هر نوع فوکوسی (چه کلیک ماوس، چه Tab) فعال می‌شه، ولی :focus-visible هوشمندانه‌تره:

/* روش قدیمی: outline حتی با کلیک ماوس هم ظاهر می‌شه */
.btn:focus {
  outline: 2px solid #3b82f6;
}

/* روش بهتر: outline فقط برای navigate با کیبورد */
.btn:focus-visible {
  outline: 2px solid #3b82f6;
}

این تفاوت خصوصاً برای دکمه‌هایی که با کلیک زیاد استفاده می‌شن (نه Tab) مهمه؛ چون خیلی از کاربرهای ماوس، outline رو یه «نویز بصری» غیرضروری می‌بینن، در حالی که کاربرهای کیبورد بهش کاملاً نیاز دارن.

نکته مهم: هیچ‌وقت focus-visible رو به این معنی نگیرید که می‌تونید فوکوس رو برای کلیک ماوس کاملاً حذف کنید. نکته اینه که مرورگر خودش تصمیم می‌گیره کِی نشون بده، نه این‌که شما دستی جداشون کنید. اگه به‌جای :focus-visible از :focus استفاده کنید ولی outline رو حذف کنید، دیگه هیچ‌کس (نه کاربر ماوس، نه کیبورد) نشانه‌ای نمی‌بینه.

اشتباه رایج: تست نکردن فوکوس با کیبورد واقعی

خیلی از توسعه‌دهنده‌ها صفحه رو فقط با ماوس تست می‌کنن و هیچ‌وقت خودشون Tab نمی‌زنن تا ببینن ترتیب فوکوس و نشانگرش چطوره. یه تست ساده و سریع: کل یه صفحه رو فقط با کیبورد (Tab، Shift+Tab، Enter) navigate کنید و ببینید همیشه واضحه که الان کجا هستید. اگه یه‌جایی گم شدید، یعنی کاربر واقعی هم گم می‌شه.

جمع‌بندی

نشانگر فوکوس، تنها راه ارتباطی کاربرهای کیبورد با صفحه‌ست و هیچ‌وقت نباید بدون جایگزین حذف بشه. از :focus-visible برای نشون دادن هوشمندانه‌ی فوکوس (فقط وقتی واقعاً لازمه) استفاده کنید، outline-offset رو برای خوانایی بهتر اضافه کنید، و مطمئن بشید رنگ outline کنتراست کافی داره. برای امنیت بیشتر تو حالت‌های کنتراست بالای سیستم‌عامل، ترکیب outline با box-shadow از تکیه‌ی کامل به یکی امن‌تره.