CSS چهار متد مربوط به focus دارد که همگی رفتار متفاوتی از خود نشان می‌دهند. این متدها حتی بسته به المنت‌هایی که از آن‌ها استفاده می‌کنیم می‌توانند متفاوت رفتار کنند. در این مقاله قصد داریم هر چهار متد focus را باهم بررسی کنیم و با تفاوت‌های آن‌ها بیشتر آشنا شویم و یاد بگیریم که چه زمانی باید از کدام یک از این متدها در پروژه خود استفاده کنیم.

Focus در CSS چیست؟

قبل از اینکه به بررسی متدهای focus بپردازیم، ابتدا باید بدانیم حالت focus چیست. هنگامی که یک المنت در حالت focus قرار می‌گیرد به این معنی است که در حال حاضر توسط کاربر انتخاب شده است. این موضوع ممکن است زمانی اتفاق بیفتد که کاربر روی یک المنت کلیک کند، یا از کلید Tab برای حرکت بین المنت‌های موجود در صفحه استفاده کند و یا حتی زمانی که کاربر با استفاده از screen reader با یک المنت در صفحه تعامل داشته باشد.

حالت فوکوس به دلایل دسترسی بسیار مهم است، زیرا به کاربران کمک می‌کند تا متوجه شوند که در کدام قسمت یک صفحه هستند و با چه المنتی تعامل دارند. به عنوان مثال تصور کنید درحال پر کردن یک فرم هستیم ولی نمی‌دانیم در آن لحظه کدام فیلد را تکمیل می‌کنیم. اگر حالت‌های focus وجود نداشت، وب به این صورت مبهم بود.

:focus

متد اصلی فوکوس pseudo-class :focus است. این متد همان چیزی است که اکثر توسعه‌دهندگان هنگام کار کردن با استایل‌های focus در CSS به آن فکر می‌کنند. اما این pseudo-class مشکلات زیادی به همراه دارد.

button {
  background-color: blue;
}

button:focus {
  background-color: red;
}

استایل‌های داخلی pseudo-class :focus هر زمان که بر روی یک المنت focus شود، اعمال می‌شوند. مهم نیست که ما با کلیک کردن بر روی المنت، با پیمایش از طریق کیبورد یا با استفاده از screen readerها و غیره بر روی آن فوکوس کرده باشیم، استایل‌های focus همیشه بر روی المنت مورد نظر اعمال شده و به نمایش درمی‌آیند. مشاهده مثال مربوط به متد :focus در این لینک امکان‌پذیر می‌باشد.

این موضوع اکثرا ایده‌آل نیست. زیرا وقتی روی دکمه‌ای کلیک می‌کنیم، معمولاً نمی‌خواهیم استایل‌های focus پس از اتمام کلیک بر روی آن نشان داده شود، اما می‌خواهیم حالت focus در هنگام استفاده از کیبورد ادامه داشته باشد، زیرا این حالت focus می‌گوید: کاربر در کدام قسمت صفحه قرار دارد.

:focus-visible

ما در بخش قبل اشاره کردیم که چرا :focus همیشه ایده‌آل نیست زیرا استایل‌های focus را بدون توجه به اینکه المنت چگونه فوکوس شده است، نشان می‌دهد. اینجاست که pseudo-class :focus-visible در CSS مطرح می‌شود. این pseudo-class کمی هوشمندتر از :focus است، زیرا تنها زمانی استایل‌های focus را نشان می‌دهد که مرورگر تشخیص دهد که کاربر به آن استایل‌‌ها نیاز دارد تا بداند در کجای صفحه قرار دارد و در حال حاضر روی چه المنتی فوکوس کرده است.

button {
  background-color: blue;
}

button:focus-visible {
  background-color: red;
}

باتوجه به مثالی که در این لینک قابل مشاهده است، می‌بینیم که هنگام کلیک کردن بر روی المنت هیچ استایل focus را نشان نمی‌دهد. اما اگر از کیبورد برای پیمایش به المنت مورد نظر استفاده کنیم، استایل‌های focus را مشاهده می‌کنیم.

نکته ای که باید در مورد :focus-visible به آن توجه کنیم این است که وقتی روی المنت‌های مختلف استفاده می‌شود متفاوت عمل می‌کند. به عنوان مثال، اگر از :focus-visible در یک المنت input استفاده کنیم، استایل focus را بدون توجه به هر چیزی نشان می‌دهد. فرقی نمی‌کند روی input کلیک کنیم یا از کیبورد استفاده کنیم، همیشه استایل‌های focus را اعمال کرده و به نمایش می‌گذارد. دلیل این اتفاق این دلیل است که مرورگر مهم می‌داند که استایل‌های focus روی المنت‌های input بدون توجه به اینکه چگونه فوکوس شده‌اند، نشان داده شود. می‌توانیم مثال مربوط به input را در این لینک ببینیم.

input {
  border-color: blue;
}

input:focus-visible {
  border-color: red;
}

:focus-within

pseudo-class :focus-within کمی متفاوت از دو متد focus قبلی است. این pseudo-class برای اعمال استایل‌ها به یک المنت parent بر اساس وضعیت :focus المنت‌های child آن استفاده می‌شود. اگر هر یک از childها حالت :focus را نشان دهد، parent نیز حالت :focus-within را نشان خواهد داد.

.container {
  border-color: blue;
}

.container:focus-within {
  border-color: red;
}

مثال مربوط به متد :focus-within در این لینک قابل مشاهده می‌باشد. در این مثال یک container وجود دارد و زمانی که بر روی یکی از childهایش فوکوس می‌شود یک حاشیه قرمز رنگ نشان می‌دهد. سه دکمه در آن container وجود دارد. اولی دارای استایل :focus است، دومی دارای استایل :focus-visible است و سومی استایل focus ندارد. همانطور که می‌بینیم، مهم نیست که روی کدام دکمه کلیک کنیم، container همیشه استایل‌های :focus-within را نشان می‌دهد، زیرا یکی از childهای آن focus شده است.

دانستن این نکته مهم است که المنت‌های child نیازی به تعریف استایل focus برای parent ندارند تا حالت :focus-within را نشان دهند. تا زمانی که یکی از childها فوکوس را داشته باشد، parent حالت :focus-within را نشان خواهد داد. این کار با هر المنتی که قابل focus باشد کار می‌کند، نه فقط دکمه‌ها.

متد چهارم focus

متد focus نهایی کمی متفاوت است زیرا هیچ pseudo class  داخلی CSS برای :focus-visible-within وجود ندارد. در عوض باید CSS selector سفارشی خود را بنویسیم که همین کار را انجام می‌دهد. این selector سفارشی نحوه کار :focus-within و :focus-visible را ترکیب می‌کند تا یک متد focus ایجاد کند که فقط زمانی استایل‌های focus را به نمایش می‌گذارد که child یک المنت استایل‌های :focus-visible خود را نشان دهد.

.container {
  border-color: blue;
}

.container:has(:focus-visible) {
  border-color: red;
}

مثال مربوط به متد :focus-visible-within را نیز می‌توانیم در این لینک بررسی کنیم. ما در این مثال تقریباً همان کد مثال قبل را داریم، اما یک المنت input به container اضافه کرده‌ایم. این المنت input دارای یک استایل :focus می‌باشد که روی آن اعمال شده است. این container فقط زمانی استایل‌های سفارشی :focus-visible-within را نشان می‌دهد که ما از کیبورد برای پیمایش به هر یک از دکمه‌ها استفاده کنیم یا وقتی که به هر نحوی بر روی المنت input فوکوس نماییم. اگر روی هر یک از دکمه‌ها کلیک کنیم، container استایل‌های سفارشی :focus-visible-within را نشان نمی‌دهد.

نحوه عملکرد این :focus-visible-within با استفاده از pseudo element :has برای انتخاب .container فقط در صورتی است که حداقل یک المنت child دارای pseudo-class :focus-visible باشد.

جمع‌بندی

در این مقاله سعی کردیم متدهای مختلف مربوط به focus در CSS را بررسی کنیم تا هم با تفاوت‌های آن‌ها آشنا شویم و هم بدانیم که بسته به ویژگی‌های پروژه‌ای که داریم باید کدام یک از آن‌ها را مورد استفاده قرار دهیم.