ارتباط بین عناصر: آشنایی با Combinatorها

تا اینجا Selectorهایی دیدیم که مستقیماً یک عنصر رو، بدون توجه به جایگاهش نسبت به بقیه، هدف قرار می‌دادن. اما خیلی وقت‌ها نیاز داریم بر اساس رابطه یک عنصر با عنصر دیگه (مثلاً «این پاراگراف که داخل این div است» یا «این عنصر که بلافاصله بعد از آن است») انتخاب انجام بدیم. اینجا نوبت Combinatorهاست.

Combinator چیست؟

Combinator نمادیه که بین دو Selector قرار می‌گیره و رابطه ساختاری بین اون دو رو مشخص می‌کنه. چهار Combinator اصلی در CSS وجود داره که در این درس با سه‌تای مهم و پرکاربردشون آشنا می‌شیم.

۱. Descendant Combinator (فاصله خالی)

Descendant Combinator با یک فاصله (Space) بین دو Selector نمایش داده می‌شه و هر عنصری رو انتخاب می‌کنه که در هر عمقی داخل عنصر اول قرار گرفته باشه؛ چه فرزند مستقیم باشه، چه نوه، چه هر سطح عمیق‌تر.

article p {
  line-height: 1.7;
}
<article>
  <p>این پاراگراف مستقیماً داخل article است.</p>
  <div>
    <p>این پاراگراف هم انتخاب می‌شود، با اینکه یک سطح عمیق‌تر است.</p>
  </div>
</article>

<p>این پاراگراف خارج از article است و انتخاب نمی‌شود.</p>

در این مثال، هر دو پاراگراف داخل article انتخاب می‌شن؛ چه در سطح مستقیم باشن چه داخل یک div میانی. تنها پاراگرافی که انتخاب نمی‌شه، اونیه که کلاً بیرون از article قرار داره.

۲. Child Combinator (علامت >)

Child Combinator با علامت بزرگ‌تر (>) نمایش داده می‌شه و برخلاف Descendant، فقط فرزندان مستقیم عنصر اول رو انتخاب می‌کنه؛ نه نوه‌ها یا سطوح عمیق‌تر.

article > p {
  font-weight: bold;
}
<article>
  <p>این فرزند مستقیم article است و انتخاب می‌شود.</p>
  <div>
    <p>این پاراگراف فرزند مستقیم article نیست و انتخاب نمی‌شود.</p>
  </div>
</article>

در این مثال، فقط پاراگراف اول Bold می‌شه؛ چون مستقیماً داخل article قرار داره. پاراگراف دوم که داخل یک div واسط قرار گرفته، فرزند مستقیم article محسوب نمی‌شه و انتخاب نمی‌شه.

تفاوت کلیدی Descendant و Child

Combinator Syntax چه چیزی را انتخاب می‌کند
Descendant A B هر عنصر B در هر عمقی داخل A
Child A > B فقط عنصر B که فرزند مستقیم A است

۳. Next-sibling Combinator (علامت +)

Next-sibling Combinator با علامت بعلاوه (+) نمایش داده می‌شه و عنصری رو انتخاب می‌کنه که بلافاصله بعد از عنصر اول، و در همون سطح (Sibling)، قرار گرفته باشه.

h2 + p {
  margin-top: 0;
}
<h2>عنوان بخش</h2>
<p>این پاراگراف بلافاصله بعد از h2 است و انتخاب می‌شود.</p>
<p>این پاراگراف دوم است و انتخاب نمی‌شود.</p>

فقط اولین پاراگراف بعد از h2 انتخاب می‌شه؛ چون دقیقاً و بی‌واسطه بعد از اون قرار داره. پاراگراف دوم، هرچند sibling عنصر اول محسوب می‌شه، ولی بلافاصله بعد از h2 نیست، پس انتخاب نمی‌شه.

۴. Subsequent-sibling Combinator (علامت ~)

Subsequent-sibling Combinator با علامت تیلد (~) نمایش داده می‌شه و تمام عناصر Sibling بعد از عنصر اول رو انتخاب می‌کنه، نه فقط اولی.

h2 ~ p {
  color: gray;
}
<h2>عنوان بخش</h2>
<p>این پاراگراف انتخاب می‌شود.</p>
<div>یک div میان‌شان</div>
<p>این پاراگراف هم انتخاب می‌شود.</p>

در این مثال، هر دو پاراگراف انتخاب می‌شن؛ حتی با اینکه یک div بین اون‌ها فاصله انداخته. تنها شرط، اینه که این پاراگراف‌ها بعد از h2 و در همون سطح (Sibling) قرار داشته باشن؛ فرقی نمی‌کنه بلافاصله باشه یا نه.

مقایسه کامل چهار Combinator

Combinator Syntax رابطه موردنیاز
Descendant A B B در هر عمقی داخل A
Child A > B B فرزند مستقیم A
Next-sibling A + B B بلافاصله بعد از A، در همان سطح
Subsequent-sibling A ~ B B در هر جای بعد از A، در همان سطح

یک مثال ترکیبی برای جمع‌بندی

.card p {
  color: #333;
}

.card > h3 {
  color: navy;
}

.card h3 + p {
  font-weight: bold;
}

.card h3 ~ span {
  color: green;
}
<div class="card">
  <h3>عنوان کارت</h3>
  <p>این پاراگراف هم رنگ عمومی کارت را دارد، هم بولد است.</p>
  <span>این عنصر سبز است.</span>
</div>

در این مثال ترکیبی:

  • .card p (Descendant) رنگ همه پاراگراف‌های داخل کارت رو تنظیم می‌کنه
  • .card > h3 (Child) فقط h3ای که فرزند مستقیم .card است رو رنگ navy می‌کنه
  • .card h3 + p (Next-sibling) فقط پاراگرافی که بلافاصله بعد از h3 اومده رو Bold می‌کنه
  • .card h3 ~ span (Subsequent-sibling) هر span بعد از h3، در هر فاصله‌ای، رو سبز می‌کنه

نکات مهم

  • Combinatorها همیشه رابطه بین دو (یا چند) Selector رو مشخص می‌کنن، نه یک Selector مستقل.
  • فاصله خالی (Descendant) پرکاربردترین Combinator‌ه، ولی گاهی به‌خاطر عدم محدودیت عمق، می‌تونه باعث انتخاب ناخواسته عناصر عمیق‌تر بشه.
  • Sibling Combinatorها (+ و ~) فقط عناصری رو انتخاب می‌کنن که بعد از عنصر اول اومدن، نه قبلش.

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

  • قاطی کردن Descendant (A B) با Child (A > B)؛ اولی همه سطوح رو شامل می‌شه، دومی فقط یک سطح.
  • فراموش کردن اینکه Next-sibling (+) فقط اولین Sibling بعدی رو می‌گیره، نه همه.
  • تصور اینکه Sibling Combinatorها می‌تونن عنصر قبلی رو هم انتخاب کنن؛ در حالی که این Combinatorها فقط رو به جلو کار می‌کنن.

جمع‌بندی

چهار Combinator اصلی در CSS رابطه ساختاری بین عناصر رو مشخص می‌کنن: Descendant (فاصله خالی) برای هر عمقی، Child (>) فقط برای فرزند مستقیم، Next-sibling (+) فقط برای اولین Sibling بعدی، و Subsequent-sibling (~) برای هر Sibling بعدی. تسلط بر این چهار Combinator، امکان نوشتن Selectorهای دقیق و قدرتمند رو بدون نیاز به اضافه کردن Classهای غیرضروری فراهم می‌کنه.