واکنش به تعامل کاربر: hover، focus، focus-visible و active

وارد فصل هفدهم شدیم؛ فصلی که به Pseudo-classها و Pseudo-elementها اختصاص داره. در فصل ۳ (درس ۳-۵)، به‌طور مقدماتی با مفهوم Pseudo-class آشنا شدیم. حالا وقتشه این‌ها رو، دسته‌بندی‌شده و کامل، ببینیم؛ شروع می‌کنیم با مهم‌ترین دسته: حالت‌های تعاملی که به رفتار کاربر (موس، صفحه‌کلید) واکنش نشون می‌دن.

hover: وقتی موس روی عنصر قرار می‌گیرد

.button {
  background-color: royalblue;
  transition: background-color 0.2s;
}

.button:hover {
  background-color: darkblue;
}

:hover، فعال می‌شه وقتی نشانگر موس، روی یک عنصر قرار بگیره؛ و به‌محض دور شدن موس، غیرفعال می‌شه. این حالت، فقط روی دستگاه‌هایی معنا داره که واقعاً موس دارن؛ روی دستگاه‌های لمسی (موبایل، تبلت)، رفتار :hover، معمولاً کمی متفاوت و کمتر قابل‌پیش‌بینیه (چون مفهوم «قرار گرفتن روی یک عنصر بدون کلیک» در لمس، اصلاً وجود نداره).

focus: وقتی یک عنصر، هدف تعامل صفحه‌کلید است

input:focus {
  border-color: royalblue;
  outline: 2px solid royalblue;
}

:focus، فعال می‌شه وقتی کاربر، با کلیک یا با کلید Tab، روی یک عنصر قابل‌فوکوس (مثل input، button، یا لینک) قرار بگیره. همون‌طور که در فصل ۹ (درس ۹-۶) با Outline دیدیم، این حالت، نقش حیاتی در دسترسی‌پذیری داره؛ چون تنها راه کاربرانی که با صفحه‌کلید ناوبری می‌کنن، برای فهمیدن «الان کدوم عنصر فعاله»، همینه.

مشکل :focus: فعال شدن حتی با کلیک ماوس

button:focus {
  outline: 3px solid royalblue;
}

یه مشکل رایج با :focus: این حالت، هم وقتی کاربر با Tab به یک عنصر می‌رسه فعال می‌شه، و هم وقتی کاربر، فقط با کلیک ماوس، روی همون عنصر کلیک می‌کنه. برای کاربر ماوس، دیدن یک قاب فوکوس دور دکمه‌ای که همین الان روش کلیک کرده، معمولاً غیرضروری و از نظر بصری، آزاردهنده به‌نظر می‌رسه؛ در حالی که برای کاربر صفحه‌کلید، این قاب، کاملاً ضروریه.

focus-visible: راه‌حل هوشمند این مشکل

button:focus-visible {
  outline: 3px solid royalblue;
}

button:focus:not(:focus-visible) {
  outline: none;
}

:focus-visible، Pseudo-class هوشمندتریه که مرورگر، خودش، تشخیص می‌ده که آیا نمایش نشانگر فوکوس، در این لحظه، واقعاً لازمه یا نه؛ معمولاً، فوکوس ناشی از صفحه‌کلید، همیشه :focus-visible رو فعال می‌کنه، ولی فوکوس ناشی از کلیک ماوس، اغلب این‌طور نیست (چون مرورگر، تشخیص می‌ده که کاربر، احتمالاً به یک نشانگر بصری اضافه نیاز نداره).

چرا نباید outline را کاملاً حذف کرد؟

/* اشتباه رایج و مضر */
button:focus {
  outline: none;
}

این دقیقاً همون هشداری‌ست که در فصل ۹ (درس ۹-۶) هم دادیم: حذف کامل Outline، بدون جایگزین کردنش با یک استایل مناسب، برای کاربران صفحه‌کلید، به‌شدت مضره. روش درست، استفاده از :focus-visible برای نمایش هوشمند نشانگر فوکوس، نه حذف کامل اون.

active: لحظه دقیق کلیک

.button:active {
  transform: scale(0.97);
}

:active، فعال می‌شه فقط تا زمانی که کاربر، دکمه ماوس رو، روی همون عنصر، پایین نگه داشته؛ یعنی دقیقاً لحظه کلیک کردن، نه قبل و نه بعدش. همون‌طور که در فصل ۳ (درس ۳-۵) به‌طور خلاصه اشاره کردیم، این حالت رو نباید با :hover قاطی کرد؛ اولی مربوط به قرارگیری موس، دومی مربوط به لحظه فشردن.

ترتیب نوشتن این Pseudo-classها در CSS

a:link {
  color: blue;
}

a:visited {
  color: purple;
}

a:hover {
  color: darkblue;
}

a:focus {
  outline: 2px solid royalblue;
}

a:active {
  color: red;
}

یک نکته مربوط به فصل ۲ (Cascade و Source Order): وقتی چند تا از این Pseudo-classها، هم‌زمان، روی یک عنصر معتبر باشن (مثلاً یک لینک، هم :hover شده و هم :focus)، اونی که Rule‌ش، پایین‌تر نوشته شده، برنده می‌شه (چون Specificity همه‌شون، طبق فصل ۳، برابره). به همین دلیل، یک ترتیب رایج و توصیه‌شده وجود داره (که گاهی به اختصار LVHA-Focus یا مشابه نامیده می‌شه): :link، :visited، :hover، :focus، و در آخر :active؛ این ترتیب، تضمین می‌کنه که، مثلاً، حالت :hover بتونه :visited رو Override کنه، ولی :active، همیشه بالاترین اولویت بصری رو در لحظه کلیک داشته باشه.

یک مثال کامل و ترکیبی برای یک دکمه

.button {
  background-color: #2c3e50;
  color: white;
  border: 2px solid transparent;
  transition: background-color 0.2s, transform 0.1s;
}

.button:hover {
  background-color: #34495e;
}

.button:focus-visible {
  outline: 3px solid royalblue;
  outline-offset: 2px;
}

.button:active {
  transform: scale(0.96);
}

در این مثال، هر چهار حالت، نقش مکمل و مستقلی دارن: :hover، بازخورد بصری هنگام معلق بودن موس؛ :focus-visible، نشانگر دسترسی‌پذیر برای کاربران صفحه‌کلید؛ و :active، بازخورد لحظه‌ای کلیک، با یک انیمیشن کوچک فشردگی.

نکات مهم

  • :hover فقط با موس معنا دارد و روی دستگاه‌های لمسی، رفتار متفاوتی دارد.
  • :focus-visible، برخلاف :focus ساده، فقط زمانی که واقعاً لازم است (معمولاً هنگام ناوبری با صفحه‌کلید)، نشانگر فوکوس را نمایش می‌دهد.
  • ترتیب نوشتن این Pseudo-classها در CSS مهم است؛ چون Specificity برابر دارند و Source Order، تعیین‌کننده اولویت نهایی است.

اشتباهات رایج

  • حذف کامل outline در حالت :focus، بدون جایگزین کردنش با یک استایل مبتنی بر :focus-visible.
  • قاطی کردن :hover با :active؛ اولی مربوط به معلق بودن موس، دومی فقط مربوط به لحظه فشردن دکمه ماوس است.
  • نوشتن :active قبل از :hover یا :focus در فایل CSS، که می‌تواند، به‌خاطر Source Order، باعث Override نامطلوب شود.

جمع‌بندی

:hover به قرارگیری موس روی یک عنصر، :focus (و نسخه هوشمندتر آن، :focus-visible) به وضعیت فوکوس برای دسترسی‌پذیری، و :active به لحظه دقیق کلیک، واکنش نشان می‌دهند. این چهار Pseudo-class، نقش‌های مکمل و مستقلی در بازخورد بصری تعامل کاربر دارند و ترتیب نوشتن آن‌ها در CSS، به‌خاطر Specificity برابرشان، اهمیت دارد.