CSS birleştiricileri (combinators), iki seçiciyi belge ağacındaki ilişkilerine göre bağlar. Dört yaygın birleştirici vardır: alt öğe birleştiricisi (boşluk, div span) herhangi bir derinlikteki torunu, çocuk birleştiricisi (div > span) yalnızca doğrudan çocuğu, sonraki kardeş birleştiricisi (h2 + p) hemen ardından gelen kardeşi, sonraki tüm kardeşler birleştiricisi (h2 ~ p) ise aynı ebeveyn altında sonra gelen bütün kardeşleri seçer. Bunlara ek olarak tablo sütunları için tanımlanmış || birleştiricisi vardır.

Bu yazıda her birleştiricinin tam olarak neyi seçtiğini, karmaşık seçicilerin nasıl okunduğunu ve en çok karıştırılan durumları örneklerle anlatıyoruz. Tek bir öğeyi adına, sınıfına veya niteliğine göre seçmek CSS seçiciler yazısının konusudur; burada o seçicileri birbirine bağlamayı öğreneceksiniz.

Karmaşık seçici nedir ve nasıl okunur?

Karmaşık seçici nedir ve nasıl okunur? a#secili > .ikon, .kutu h2 + p

MDN seçicileri üç düzeyde tanımlar. Basit seçici tek bir bileşendir (p, .not, [href]). Arada boşluk olmadan yan yana yazılan basit seçiciler compound seçici oluşturur ve tek bir öğe üzerindeki koşulları ifade eder. Bir veya daha fazla basit ya da compound seçicinin birleştiricilerle ayrılmasıyla da karmaşık seçici (complex selector) elde edilir; bu yapı birden fazla öğe üzerindeki koşulları birlikte ifade eder.

Karmaşık seçicileri sağdan sola okumak işinizi kolaylaştırır. En sağdaki parça, stilin gerçekten uygulanacağı öğedir; soldaki parçalar o öğenin hangi bağlamda bulunması gerektiğini anlatır. MDN'in örnekleriyle:

  • a#secili > .ikon: ikon sınıflı öğeleri seçer, ama yalnızca id değeri secili olan bir <a> öğesinin doğrudan çocuklarıysa.
  • .kutu h2 + p: bir h2 öğesinin hemen ardından gelen p öğelerini seçer, ama o h2 öğesi kutu sınıflı bir öğenin içindeyse.
BirleştiriciYazımSeçtiği öğe
Alt öğe (descendant)A BA içindeki her derinlikteki B
Çocuk (child)A > BA öğesinin doğrudan çocuğu olan B
Sonraki kardeş (next-sibling)A + BA ile aynı ebeveyne sahip, A dan hemen sonra gelen B
Sonraki tüm kardeşler (subsequent-sibling)A ~ BA ile aynı ebeveyne sahip, A dan sonra gelen tüm B
Sütun (column)A || BA sütun öğesinin kapsamına giren B hücreleri

Alt öğe birleştiricisi: boşluk

Alt öğe birleştiricisi genellikle tek bir boşlukla yazılır. İkinci seçiciyle eşleşen öğeyi, birinci seçiciyle eşleşen bir atası varsa seçer. Ata; ebeveyn, ebeveynin ebeveyni ve daha yukarısı olabilir, yani derinlik sınırı yoktur. Bu birleştiriciyi kullanan seçicilere alt öğe seçicileri (descendant selectors) denir.

MDN teknik bir ayrıntıyı da not eder: bu birleştirici aslında başka bir birleştiricinin bulunmadığı yerde iki seçici arasındaki bir veya daha fazla CSS boşluk karakteridir. Boşluk, satır başı, form feed, yeni satır ve sekme karakterleri sayılır; bu boşlukların arasında CSS yorumları da bulunabilir.

css
li {
  list-style-type: disc;
}
li li {
  list-style-type: circle;
}
html
<ul>
  <li>
    Öğe 1
    <ul>
      <li>Alt öğe A</li>
      <li>Alt öğe B</li>
    </ul>
  </li>
</ul>

Sonuç: dış listedeki öğeler dolu daire, iç listedeki öğeler boş daire işaretiyle gösterilir. İçteki li öğeleri bir li atasına sahip olduğu için li li seçicisiyle eşleşir; dıştaki li öğelerinin ise böyle bir atası yoktur.

Çocuk birleştiricisi: >

Çocuk birleştiricisi (>) iki seçici arasına yazılır ve ikinci seçiciyle eşleşen öğeyi yalnızca birinci seçiciyle eşleşen öğenin doğrudan çocuğuysa seçer. Alt öğe birleştiricisinden daha katıdır: arada başka bir öğe varsa eşleşme olmaz. > işaretinin etrafındaki boşluklar isteğe bağlıdır, ama okunabilirlik için önerilir.

css
span {
  background-color: aqua;
}
div > span {
  background-color: yellow;
}
html
<div>
  <span>
    Span 1, div içinde.
    <span>Span 2, div içindeki span'in içinde.</span>
  </span>
</div>
<span>Span 3, div dışında.</span>

Sonuç: yalnızca Span 1 sarı olur, çünkü div öğesinin doğrudan çocuğu odur. Span 2 bir span öğesinin çocuğudur; div onun atasıdır ama ebeveyni değildir, bu yüzden aqua kalır. Span 3 hiçbir div içinde değildir. Aynı örnekte div span yazsaydınız Span 1 ve Span 2 birlikte sarı olurdu.

Sonraki kardeş birleştiricisi: +

Sonraki kardeş birleştiricisi: +

Sonraki kardeş birleştiricisi (+), ikinci öğeyi yalnızca birinci öğenin hemen ardından geliyorsa ve ikisi aynı ebeveynin çocuklarıysa seçer. "Kardeş", belge ağacında aynı ebeveyni paylaşan öğe demektir.

css
/* herhangi bir görselin hemen ardından gelen paragraflar */
img + p {
  font-weight: bold;
}

/* türünün ilki olan li öğesinin hemen ardından gelen li */
li:first-of-type + li {
  color: red;
  font-weight: bold;
}
/* sonuç: üç maddelik listede yalnızca ikinci madde kırmızı ve kalın */

Bu birleştiricinin klasik kullanımı, art arda gelen öğeler arasına boşluk eklemektir: p + p yalnızca kendinden önce bir paragraf bulunan paragrafları seçtiği için ilk paragrafı etkilemez.

Önceki kardeşi seçmek: :has() ile

Birleştiriciler her zaman ileri doğru çalışır; yani bir öğenin önündeki kardeşi doğrudan seçemezsiniz. MDN, bunun için sonraki kardeş birleştiricisinin :has() içinde kullanılabileceğini gösterir:

css
/* hemen ardından türünün sonuncusu olan bir li gelen li */
li:has(+ li:last-of-type) {
  color: red;
  font-weight: bold;
}
/* sonuç: dört maddelik listede üçüncü madde kırmızı ve kalın */

:has() ilişkisel bir pseudo-class'tır ve kendi kuralları vardır; ayrıntıları :has() ve diğer mantıksal seçiciler yazısında bulabilirsiniz. Tarayıcı desteği için MDN sayfasındaki uyumluluk tablosuna bakın.

Sonraki tüm kardeşler birleştiricisi: ~

Tilde işaretiyle yazılan birleştirici (~), ikinci seçiciyle eşleşen ve birinci öğeden sonra gelen bütün kardeşleri seçer. Hemen ardından gelmeleri gerekmez; arada başka türden öğeler bulunabilir. Tek şart, aynı ebeveyni paylaşmalarıdır.

css
p ~ span {
  color: red;
}
html
<article>
  <span>Kırmızı değil: paragraftan önce geliyor.</span>
  <p>Bir paragraf.</p>
  <code>Biraz kod.</code>
  <span>Kırmızı: paragraftan sonra, arada başka öğe olsa da.</span>
  <h1>Başlık</h1>
  <span>Kırmızı: aynı ebeveyn, paragraftan sonra.</span>
</article>
<span>Kırmızı değil: paragrafla aynı ebeveyni paylaşmıyor.</span>

Bu örnek, ~ birleştiricisinin iki sınırını birlikte gösterir: paragraftan önce gelen kardeş seçilmez ve article dışındaki span öğesi, paragrafla aynı ebeveyne sahip olmadığı için hiç değerlendirmeye girmez.

Birleştiricileri zincirlemek

Birleştiriciler art arda kullanılabilir. MDN'in örneğinde .foo p ~ span, ebeveyni ya da daha yukarıdaki bir atası foo sınıflı olan bir paragrafın sonraki span kardeşlerini seçer. .foo p ~ .foo span ise başka bir şey söyler: paragrafın kardeşi olan bir .foo öğesinin içindeki span öğelerini seçer. Bu iki seçici aynı belgede farklı öğeleri hedefler; sağdan sola okumak farkı görmeyi kolaylaştırır.

css
h2 + p ~ p {
  font-style: italic;
}
h2 + p + p {
  color: red;
}
/* sonuç: h2'den hemen sonraki paragraftan sonra gelen tüm
   paragraflar italik; h2'den sonraki ikinci paragraf ayrıca kırmızı */

Sütun birleştiricisi: ||

Sütun birleştiricisi (||), ikinci seçiciyle eşleşen hücreleri, birinci seçiciyle eşleşen sütun öğesinin kapsamına giriyorlarsa seçer. Örneğin col.secili || td, secili sınıflı <col> öğesinin sütununa ait tablo hücrelerini hedefler.

css
col.secili || td {
  background: gray;
  color: white;
}

Bunlardan ayrı olarak tek dikey çizgiyle yazılan ad alanı ayırıcısı (|) da vardır. @namespace kuralıyla birlikte kullanılır ve tür seçicileri belirli bir ad alanıyla sınırlar; örneğin bir SVG ad alanı tanımlandıktan sonra svg|a yalnızca SVG içindeki bağlantıları seçer.

Uygulamalı örnek: bir makale sayfasını birleştiricilerle düzenlemek

Birleştiricilerin gücü, HTML'e ek sınıf koymadan yapıya göre stil verebilmenizdir. Aşağıdaki makale gövdesinde yalnızca kapsayıcıda bir sınıf bulunuyor; geri kalan her şey öğe türleri ve aralarındaki ilişkilerle seçiliyor.

html
<article class="makale">
  <h2>Giriş</h2>
  <p>Giriş paragrafı.</p>
  <p>İkinci paragraf.</p>
  <ul>
    <li>Madde</li>
  </ul>
  <aside>
    <p>Kenar notu paragrafı.</p>
  </aside>
  <h2>Sonuç</h2>
  <p>Son paragraf.</p>
</article>
css
/* 1. Yalnızca makalenin doğrudan çocuğu olan paragraflar */
.makale > p {
  line-height: 1.7;
}

/* 2. Her başlığın hemen ardından gelen ilk paragraf */
.makale h2 + p {
  font-size: 1.1em;
}

/* 3. Bir paragraftan hemen sonra gelen paragraf: girinti */
.makale p + p {
  text-indent: 1.5em;
}

/* 4. Bir h2 başlığından sonra gelen tüm listeler */
.makale h2 ~ ul {
  padding-left: 1.5rem;
}

Sonuçları sırayla inceleyelim. Birinci kural çocuk birleştiricisi kullandığı için "Giriş paragrafı", "İkinci paragraf" ve "Son paragraf" satırlarına uygulanır; aside içindeki kenar notu paragrafı makalenin torunu olduğu, ama doğrudan çocuğu olmadığı için bu satır yüksekliğini almaz. İkinci kural her iki h2 başlığının hemen ardından gelen paragrafı, yani "Giriş paragrafı" ile "Son paragraf" satırlarını biraz büyütür.

Üçüncü kural yalnızca "İkinci paragraf" ile eşleşir, çünkü önünde aynı ebeveyni paylaşan bir paragraf bulunan tek paragraf odur. Kenar notu paragrafının önünde bir kardeş paragraf yoktur; "Son paragraf" satırının hemen önünde ise bir h2 durur. Dördüncü kural, ilk h2 öğesinden sonra gelen ul kardeşine sol iç boşluk verir; listeden önce başka öğeler bulunması bu eşleşmeyi engellemez.

Bu örnekte HTML'e yeni bir paragraf eklediğinizde stillerin kendiliğinden doğru yere uygulandığını görürsünüz: yeni paragraf bir başlıktan hemen sonra gelirse büyür, başka bir paragraftan sonra gelirse girintili olur. Birleştiricilerle yazılmış kurallar, içeriğin sırasını ve yapısını anlatan HTML ile birlikte çalışır.

Doğru birleştiriciyi seçmek için üç soru

Doğru birleştiriciyi seçmek için üç soru: Hedef öğe, bağlam öğesinin içinde mi?, Hedef öğe, bağlam öğesiyle aynı ebeveyni mi paylaşıyor?, Hedef öğe bağlam öğesinden önce mi...

Bir kural yazarken hangi birleştiriciye ihtiyacınız olduğunu şu sorularla hızlıca belirleyebilirsiniz:

  • Hedef öğe, bağlam öğesinin içinde mi? Evetse alt öğe ya da çocuk birleştiricisi gerekir. İç içe yapıların derin katmanlarını da etkilemek istiyorsanız boşluk, yalnızca ilk düzeyi istiyorsanız > kullanın.
  • Hedef öğe, bağlam öğesiyle aynı ebeveyni mi paylaşıyor? Evetse kardeş birleştiricilerinden biri gerekir. Yalnızca hemen sonraki öğe için +, sonra gelen hepsi için ~ seçin.
  • Hedef öğe bağlam öğesinden önce mi geliyor ya da onun ebeveyni mi? Bu durumda hiçbir birleştirici tek başına işe yaramaz; :has() ile ilişkiyi tersine çevirmeniz gerekir.

Bu soruları yanıtlarken tarayıcının geliştirici araçlarındaki öğe ağacına bakmak, hangi öğenin hangisinin ebeveyni ya da kardeşi olduğunu kesin olarak görmenizi sağlar. Ekranda yan yana duran iki öğe, belge ağacında çok farklı yerlerde olabilir.

Birleştiriciler ve özgüllük

Birleştiriciler seçimi daraltır ama özgüllük ağırlığına hiçbir şey eklemez. div > p ile div p aynı özgüllüğe sahiptir; ikisi de iki tür seçiciden oluşur. MDN ayrıca belge ağacındaki yakınlığın özgüllüğü etkilemediğini vurgular: body h1 ile html h1 eşit ağırlıktadır ve hangisi sonra yazıldıysa o kazanır. Hesaplamanın tamamı özgüllük hesaplama yazısında.

CSS nesting ile birleştiricileri iç içe kurallar içinde de yazabilirsiniz. Örneğin h2 { & + p { ... } } yazımı h2 + p ile aynı öğeyi seçer. Bu yazım biçimi CSS nesting yazısında ayrıntılı olarak anlatılıyor.

Sık yapılan hatalar

  • Boşluğun anlamını unutmak: .kart .baslik ile .kart.baslik çok farklıdır. İlki kartın içindeki başlığı, ikincisi her iki sınıfa birden sahip tek bir öğeyi seçer.
  • ~ birleştiricisinin önceki kardeşleri de seçtiğini sanmak: Yalnızca sonra gelenleri seçer. Önceki kardeş için :has() gerekir.
  • Kardeşlerin aynı ebeveyni paylaşması gerektiğini atlamak: Farklı kapsayıcılardaki öğeler + ya da ~ ile ilişkilendirilemez.
  • > ile derin seçim beklemek: Arada bir sarmalayıcı öğe varsa çocuk birleştiricisi eşleşmez.
  • Gereğinden uzun zincirler: body main article section p gibi uzun zincirler HTML yapısı değiştiğinde kırılır. Bağlamı belirten bir sınıf çoğu zaman yeterlidir.

Sık Sorulan Sorular

Boşluk ile > arasındaki fark nedir?

Boşluk (alt öğe birleştiricisi) her derinlikteki torunları seçer; > yalnızca doğrudan çocukları. Arada bir sarmalayıcı öğe varsa > eşleşmez.

+ ile ~ arasındaki fark nedir?

+ yalnızca hemen ardından gelen tek kardeşi, ~ sonra gelen tüm kardeşleri seçer. İkisi de aynı ebeveyni paylaşan öğelerle çalışır.

CSS ile ebeveyn öğe seçilebilir mi?

Birleştiricilerle seçilemez, çünkü hepsi aşağı ya da ileri doğru çalışır. :has() pseudo-class'ı ise belirli bir çocuğu ya da kardeşi olan öğeyi seçmenize izin verir; ayrıntılar :has() yazısında.

Birleştiricilerin etrafına boşluk koymak zorunlu mu?

>, +, ~ ve || için değildir; MDN boşlukları isteğe bağlı ama önerilen olarak gösterir. Alt öğe birleştiricisi ise zaten boşluğun kendisidir.

Birleştirici eklemek bir kuralı daha güçlü yapar mı?

Doğrudan yapmaz. Birleştiricinin kendisi özgüllüğe katkı vermez; ağırlığı artıran, zincire eklediğiniz seçicilerdir. .makale p ile .makale > p aynı ağırlıktadır ve çakışırlarsa sonra yazılan kazanır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: CSS öğrenme rehberi · CSS seçiciler · :has() ve :is() · Özgüllük hesaplama · CSS nesting