جمع‌بندی خانواده Pseudo-classها: root، target و Selectorهای تابعی مدرن

در درس‌های قبل این فصل، حالت‌های تعاملی، فرم و ساختاری رو دیدیم. این درس، آخرین درس آموزشی فصل هفدهمه و به دو دسته باقی‌مانده اختصاص داره: :root و :target (که در فصل‌های قبل، فقط اشاره کوتاهی بهشون شد)، و مرور نهایی چهار Selector تابعی مدرن (:is()، :where()، :not()، :has()) که در فصل ۳ (درس ۳-۹) کامل دیدیم.

مرور: root

:root {
  --primary-color: #1a73e8;
}

همون‌طور که در فصل ۲ (درس ۲-۵) و به‌طور کامل‌تر در فصل ۱۶، دیدیم، :root، به بالاترین عنصر ساختار سند (معادل html) اشاره می‌کنه، ولی با Specificity بالاتر از یک Type Selector ساده. کاربرد اصلیش، همون‌طور که در کل فصل ۱۶ دیدیم، تعریف CSS Custom Properties در سطح سراسری سنده.

چرا :root به‌جای html استفاده می‌شود؟

html {
  --old-style: red;
}

:root {
  --modern-style: blue;
}

هرچند :root و html، در اسناد معمولی HTML، عملاً به یک عنصر یکسان اشاره می‌کنن، ولی :root، از نظر Specificity، هم‌وزن یک Pseudo-class (یعنی معادل Class، طبق فصل ۳) محاسبه می‌شه؛ در حالی که html، فقط هم‌وزن یک Type Selector‌ه. به همین دلیل، برای تعریف متغیرهای سراسری که نباید به‌راحتی توسط یک Type Selector ساده Override بشن، :root، انتخاب رایج‌تر و امن‌تریه.

target: هدف یک لینک داخلی (Anchor)

.section {
  padding: 20px;
}

.section:target {
  background-color: lightyellow;
}
<a href="#section-2">برو به بخش ۲</a>

<div id="section-1" class="section">بخش ۱</div>
<div id="section-2" class="section">بخش ۲</div>

:target، عنصری رو هدف می‌گیره که id‌ش، دقیقاً برابر بخش Fragment (یعنی قسمت بعد از #) در آدرس فعلی صفحه باشه. در این مثال، وقتی کاربر روی لینک «برو به بخش ۲» کلیک می‌کنه، آدرس صفحه به #section-2 تغییر می‌کنه، و همون لحظه، .section:target، دقیقاً همون div با id="section-2" رو، با یک پس‌زمینه زرد، برجسته می‌کنه؛ بدون نیاز به حتی یک خط جاوااسکریپت.

یک کاربرد رایج :target: تب‌های ساده بدون جاوااسکریپت

.tab-content {
  display: none;
}

.tab-content:target {
  display: block;
}

این تکنیک، امکان ساخت یک سیستم تب یا آکاردئون ساده، فقط با لینک‌های داخلی و CSS، بدون هیچ جاوااسکریپتی رو فراهم می‌کنه؛ هرچند، برای فرم‌های پیچیده‌تر تعامل، معمولاً جاوااسکریپت، کنترل و انعطاف بیشتری می‌ده.

مرور فشرده: is()، where()، not()، has()

این چهار Selector، با جزئیات کامل، در فصل ۳ (درس ۳-۹) بررسی شدن؛ اینجا فقط یک جدول یادآوری سریع می‌بینیم، چون در دسته‌بندی این فصل (Pseudo-classها)، این‌ها هم رسماً جزو همین خانواده محسوب می‌شن.

Selector عملکرد تأثیر بر Specificity
:is() مطابقت با هر یک از چند Selector وزن بالاترین آرگومان داخلی
:where() مثل is()، ولی بدون افزودن وزن همیشه صفر
:not() معکوس کردن یک یا چند شرط وزن بالاترین آرگومان داخلی
:has() انتخاب بر اساس وجود فرزند یا رابطه داخلی وزن بالاترین آرگومان داخلی

یک کاربرد ترکیبی: :root در کنار :has()

:root:has(.modal-open) {
  overflow: hidden;
}

یک تکنیک نسبتاً پیشرفته و مدرن: می‌شه :has() رو، مستقیماً روی :root اعمال کرد؛ در این مثال، اگه در هر جای سند، یک عنصر با کلاس .modal-open وجود داشته باشه (مثلاً وقتی یک پنجره Modal بازه)، اسکرول کل صفحه (روی html)، غیرفعال می‌شه. این ترکیب، یکی از الگوهای بسیار کاربردی و مدرن CSS برای کنترل رفتار سراسری صفحه، صرفاً بر اساس وجود یک کلاس در جایی از DOM، بدون جاوااسکریپت اضافه، است.

یک مثال جامع: ترکیب همه مفاهیم این فصل

:root {
  --highlight-color: gold;
}

.section:target {
  background-color: var(--highlight-color);
}

.section:target:is(.important, .featured) {
  border: 2px solid crimson;
}

در این مثال نهایی، :root یک متغیر تعریف می‌کنه که در :target استفاده می‌شه؛ و اگه بخش هدف‌شده، هم‌زمان کلاس .important یا .featured رو هم داشته باشه (با :is())، یک بوردر اضافه هم می‌گیره. این ترکیب، نشون می‌ده چطور مفاهیم پراکنده این فصل و فصل‌های قبل (متغیرها، Pseudo-classهای تابعی، حالت‌های خاص)، در یک Rule واحد، کنار هم قرار می‌گیرن.

نکات مهم

  • :root، از نظر عملی به html اشاره می‌کند، ولی با Specificity بالاتر (هم‌وزن یک Class)، و به همین دلیل، برای تعریف متغیرهای سراسری ترجیح داده می‌شود.
  • :target، عنصری را هدف می‌گیرد که id آن، با بخش Fragment آدرس فعلی صفحه (بعد از #) مطابقت داشته باشد؛ کاربردی برای برجسته‌سازی یا نمایش/مخفی‌سازی محتوا بدون جاوااسکریپت.
  • :is()، :where()، :not() و :has()، که در فصل ۳ کامل دیده شدند، رسماً جزو خانواده Pseudo-classها هستند و می‌توانند حتی روی :root هم اعمال شوند.

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

  • استفاده از html به‌جای :root برای تعریف متغیرهای سراسری، بدون توجه به تفاوت Specificity این دو.
  • فراموش کردن این‌که :target، فقط زمانی فعال است که آدرس فعلی صفحه، دقیقاً شامل همان Fragment (#id) باشد.
  • تصور اینکه :is/:where/:not/:has، مفاهیمی جدا از خانواده Pseudo-classها هستند؛ در حالی که رسماً همین دسته محسوب می‌شوند.

جمع‌بندی

:root، معادل html با Specificity بالاتر است و پایه اصلی تعریف متغیرهای سراسری در فصل ۱۶ بود. :target، عنصری را که id آن با Fragment آدرس فعلی صفحه مطابقت دارد هدف می‌گیرد و امکان ساخت جلوه‌های تعاملی ساده، بدون جاوااسکریپت، را فراهم می‌کند. :is()، :where()، :not() و :has()، که در فصل ۳ کامل بررسی شدند، تکمیل‌کننده این خانواده‌اند و می‌توانند، حتی در ترکیب با :root، برای کنترل رفتار سراسری صفحه استفاده شوند؛ و با این جمع‌بندی، فصل هفدهم دوره را به پایان می‌رسانیم.