CSS nesting, bir stil kuralını başka bir stil kuralının içine yazmanıza olanak tanıyan yerel CSS özelliğidir. İçteki kuralın seçicisi dıştaki kuralın seçicisine göreli olarak yorumlanır: .kart { h2 { ... } } yazdığınızda tarayıcı bunu .kart h2 olarak anlar. & nesting seçicisi ise dış kuralın seçicisini tam olarak nereye yerleştireceğinizi belirtir; &:hover gibi yazımlarda ona ihtiyaç duyarsınız.
MDN, yerel nesting'in Sass gibi ön işlemcilerden temel farkını şöyle tanımlar: İç içe yazım derleme aşamasında düz CSS'e çevrilmez, doğrudan tarayıcı tarafından ayrıştırılır. Bu yüzden davranışı bazı noktalarda ön işlemcilerden ayrılır; özellikle özgüllük ve sınıf adı birleştirme konusunda. Bu yazıda & seçicisinin üç kullanımını, birleştiricileri, bileşik seçicileri, at-rule iç içe yazımını, özgüllük etkisini, yapılamayan şeyleri ve sık hataları anlatıyoruz.
Temel kullanım: & olmadan ve & ile
İçteki kuralı & kullanmadan yazdığınızda tarayıcı iki seçicinin arasına otomatik olarak bir boşluk ekler; boşluk CSS'te alt öğe (descendant) birleştiricisidir. & ile yazdığınızda ise dış seçici tam olarak & işaretinin bulunduğu yere konur. Aşağıdaki iki yazım aynı sonucu verir.
/* & olmadan */
.parent {
color: navy;
.child {
color: teal;
}
}
/* & ile */
.parent {
color: navy;
& .child {
color: teal;
}
}
/* tarayıcının ikisini de okuduğu biçim */
.parent {
color: navy;
}
.parent .child {
color: teal;
}MDN, & kullanmanın gerekli ya da yararlı olduğu üç durum sayar: seçicileri bitişik birleştirirken (bileşik seçiciler ve pseudo-class'lar), geriye dönük uyumluluk için ve okunabilirliği artırmak için; & gördüğünüzde iç içe yazım kullanıldığını hemen anlarsınız. Alt öğe, çocuk ve kardeş birleştiricilerinin kendisi birleştiriciler yazısında anlatılıyor.
MDN'nin rehberindeki form örneği bu ayrımı somutlaştırır: Bir <label> öğesinin içindeki <input> ile etiketin kardeşi olan <input> farklı biçimlendirilir. Dışarıdaki genel input kuralı domates rengi düz bir kenarlık verir; label kuralının içine yazılan input kuralı ise yalnızca etiketin içindeki alanı mavi kesik çizgili yapar. İç kural label input olarak genişlediği için etiketin dışındaki alan bu kuraldan etkilenmez.
input {
/* etiketin dışındaki input */
border: tomato 2px solid;
}
label {
font-family: system-ui;
font-size: 1.25rem;
input {
/* label input: etiketin içindeki input */
border: blue 2px dashed;
}
}Genişleme tablosu: hangi yazım neye dönüşür

Aşağıdaki tablo, .a dış seçicisiyle yazılan iç kuralların tarayıcı tarafından hangi düz seçiciye çevrildiğini özetler. Tablodaki satırların hepsi bu yazıdaki MDN örneklerine dayanır.
| İç içe yazım | Düz karşılığı | Not |
|---|---|---|
| .a { .b {} } | .a .b | Boşluk otomatik eklenir |
| .a { & .b {} } | .a .b | Aynı sonuç, & ile açık yazım |
| .a { &.b {} } | .a.b | Bileşik seçici, & zorunlu |
| .a { > .b {} } | .a > .b | Birleştiriciyle başlama |
| .a { + p {} } | .a + p | Sonraki kardeş |
| .a { :hover {} } | .a *:hover | Genellikle istenmeyen sonuç |
| .a { &:hover {} } | .a:hover | Öğenin kendi durumu |
| .a { .x & {} } | .x .a | Bağlam tersine döner |
| .a { div& {} } | div.a | Tür seçicisi önde olmalı |
| .a { @media (...) { color: red; } } | @media (...) { .a { color: red; } } | Bildirim & {} içindeymiş gibi |
Birleştiricilerle iç içe yazım
İçteki seçici bir birleştiriciyle de başlayabilir. >, + ve ~ birleştiricileri & ile ya da onsuz yazılabilir; tarayıcı dış seçiciyi başa yerleştirir. MDN'nin örneğinde her <h2> başlığından hemen sonra gelen paragraf, sonraki kardeş birleştiricisiyle hedeflenir.
h2 {
color: tomato;
+ p {
color: white;
background-color: black;
}
}
/* eşdeğeri: h2 + p { ... }
& + p { ... } yazımı da aynı sonucu verir */
.example {
font-family: system-ui;
& > a {
color: tomato;
&:hover,
&:focus {
color: ivory;
background-color: tomato;
}
}
}
/* eşdeğeri: .example > a { ... }
.example > a:hover, .example > a:focus { ... } */İkinci örnekte iki düzey iç içe yazım var: & > a kuralının içindeki &, artık .example > a seçicisini temsil eder. Seçici listesi (&:hover, &:focus) da iç içe yazılabilir ve her parça ayrı ayrı genişletilir.
Bileşik seçiciler ve pseudo-class: & zorunlu

Bir öğeyi iki sınıfla birden ya da bir durumla birlikte hedeflemek istediğinizde, yani seçicilerin arasında boşluk olmaması gerektiğinde, & işaretini boşluksuz yazmak zorundasınız. Aksi hâlde tarayıcının eklediği boşluk anlamı tamamen değiştirir.
.a {
.b {
/* .a .b: .a içindeki .b öğeleri */
}
&.b {
/* .a.b: class="a b" olan öğe */
}
}
.parent-rule {
:hover {
/* .parent-rule *:hover: üzerine gelinen HER ALT ÖĞE */
}
&:hover {
/* .parent-rule:hover: üzerine gelinen öğenin kendisi */
}
}:hover örneği iç içe yazımdaki en yaygın hatadır. & olmadan yazılan :hover, MDN'nin gösterdiği gibi .parent-rule *:hover olarak okunur ve öğenin kendisi değil, içindeki herhangi bir öğe üzerine gelindiğinde çalışır. Düğme, bağlantı ve kart gibi öğelerde durum stillerini her zaman &:hover, &:focus-visible, &::before biçiminde yazın. Pseudo-class'lar pseudo-class yazısında anlatılıyor.
& işaretini sona koymak: bağlamı tersine çevirmek
& seçicinin başında olmak zorunda değildir. Başka bir seçiciden sonra yazıldığında bağlam tersine döner: Dıştaki öğenin belirli bir ebeveynin içinde olduğu durum için stil tanımlarsınız. Bu, bir bileşenin tüm varyasyonlarını kendi kuralı içinde toplamak için kullanışlıdır. & birden çok kez de yazılabilir; .featured & & & gibi bir yazım .featured .card .card .card olarak genişler.
.card {
padding: 0.5rem;
& h2 {
color: slateblue;
.featured & {
/* :is(.card h2):is(.featured h2) ile eşdeğer */
color: tomato;
}
}
}
/* sonuç: kart başlıkları slateblue;
.featured sınıflı bir atanın içindeki kart başlıkları tomato */MDN bu örnekte iç kuralın :is(.card h2):is(.featured h2) ile eşdeğer olduğunu belirtir. card featured sınıflarına sahip bir makale içindeki <h2> hem .card h2 hem de .featured h2 koşulunu sağladığından domates rengini alır.
At-rule'ları iç içe yazmak
İçinde stil kuralı barındıran at-rule'lar da bir stil kuralının içine yerleştirilebilir. MDN'nin listesi şunlardır: @media, @supports, @layer, @scope, @container ve @starting-style. İç içe at-rule'un içine doğrudan bildirim yazabilirsiniz; bu bildirimler bir & { ... } bloğunun içindeymiş gibi davranır ve seçicisini en yakın ata stil kuralından alır.
/* iç içe yazım */
.foo {
display: grid;
@media (orientation: landscape) {
grid-auto-flow: column;
@media (width >= 1024px) {
max-inline-size: 1024px;
}
}
}
/* iç içe olmayan eşdeğer */
.foo {
display: grid;
}
@media (orientation: landscape) {
.foo {
grid-auto-flow: column;
}
}
@media (orientation: landscape) and (width >= 1024px) {
.foo {
max-inline-size: 1024px;
}
}İç içe iki @media kuralı, düz yazımda and ile birleşmiş tek bir sorguya karşılık gelir. Bu, bileşene ait tüm kırılma noktalarını bileşenin kendi kuralında tutmanızı sağlar. Media query sözdizimi media query yazısında, kapsayıcı sorguları container queries yazısında anlatılıyor.
@layer da aynı biçimde iç içe yazılabilir. İç içe katmanlar nokta ile birleşen alt katmanlar oluşturur. MDN'nin örneğinde .foo içinde yazılan @layer base ve onun içindeki @layer support, düz yazımda @layer base ve @layer base.support bloklarına dönüşür:
.foo {
@layer base {
block-size: 100%;
@layer support {
& .bar {
min-block-size: 100%;
}
}
}
}
/* eşdeğeri */
@layer base {
.foo {
block-size: 100%;
}
}
@layer base.support {
.foo .bar {
min-block-size: 100%;
}
}Katman sırası ve önceliği @layer yazısında anlatılıyor.
İç içe yazımın özgüllüğe etkisi
& seçicisinin özgüllüğü, ilişkili seçici listesindeki en yüksek özgüllüğe göre hesaplanır. MDN bunun :is() fonksiyonunun hesaplanma biçimiyle aynı olduğunu belirtir. Dış kural tek bir seçiciye sahipse fark görünmez; ama dış kuralda seçici listesi varsa sonuç şaşırtıcı olabilir.
<b class="foo">
<i>Mavi metin</i>
</b>#a, b {
& i {
color: blue;
}
}
.foo i {
color: red;
}
/* & = :is(#a, b) -> en yüksek özgüllük #a: 1-0-0
& i = 1-0-0 + 0-0-1 = 1-0-1
.foo i = 0-1-0 + 0-0-1 = 0-1-1
1-0-1 > 0-1-1, sonuç: metin mavi */Sayfada id="a" olan bir öğe hiç bulunmasa da &, listedeki kimlik seçicisinin ağırlığını taşır. Bu yüzden <b> içindeki <i> için iç içe kural, daha sonra yazılmış ve sınıf içeren .foo i kuralını yener. Düz CSS'te #a i, b i yazsaydınız b i parçası 0-0-2 ağırlığıyla eşleşir ve .foo i (0-1-1) kazanırdı; iç içe yazımın sonucu bu açıdan farklıdır. :is() ve :where() ile özgüllük yönetimi :has, :is, :where ve :not yazısında, ağırlık hesabı ise özgüllük yazısında ayrıntılı işleniyor.
Yapılamayanlar: sınıf adı birleştirme ve pseudo-element
Ön işlemcilerden gelenlerin en sık karşılaştığı sınır, metin birleştirmedir. Sass'ta .component { &__child-element { } } yazımı .component__child-element sınıfını üretir; BEM gibi adlandırma yöntemlerinde yaygındır. MDN'ye göre bu yerel CSS nesting'de mümkün değildir: Birleştirici kullanılmadığında iç içe seçici bir tür (type) seçicisi olarak ele alınır ve birleştirmeye izin vermek bu kuralı bozardı.
Benzer bir kural tür seçicileri için geçerlidir. Bileşik seçicide tür seçicisi önce gelmek zorunda olduğundan &div yazımı geçersizdir ve tüm bloğu geçersiz kılar. Doğru yazım div& biçimidir ve div.my-class olarak genişler.
.my-class {
div& {
/* div.my-class */
}
}
/* geçersiz: tür seçicisi başta olmalı */
.my-class {
&div {
}
}Üçüncü sınır pseudo-element'lerle ilgilidir. &, :is() ile eşdeğer olduğundan onunla aynı kısıtı taşır ve bir pseudo-element'i temsil edemez. MDN'nin örneğinde .foo::before kuralının içine yazılan .important & { color: red; } hiçbir şeyi boyamaz, çünkü .important :is(.foo::before) hiçbir öğeyle eşleşemez. Aynı durum iç içe at-rule için de geçerlidir: .foo::before içine yazılan @media (width < 600px) { color: red; } da etkisizdir. Pseudo-element stillerini düz seçiciyle yazın; ayrıntılar için ::before ve ::after yazısına bakabilirsiniz.
Geçersiz iç kurallar ve bildirim sırası
MDN'ye göre iç içe kurallardan biri geçersizse yalnızca o kural ve içindeki stiller yok sayılır; dış kural ve öncesindeki ya da sonrasındaki geçerli kurallar etkilenmez. Örneğin % geçerli bir seçici karakteri olmadığından & %invalid { ... } bloğu atlanır, ama hemen arkasından gelen & .valid { ... } çalışır. Bu, tek bir yazım hatasının tüm bileşeni bozmaması açısından önemli bir güvencedir.
İç içe bildirimler kuralı ise sırayla ilgilidir: Kurallar belgede yazıldıkları sırayla ayrıştırılır. Aşağıdaki örnekte önce background-color, sonra @media bloğu, en son color: black işlenir. Dolayısıyla ekran ortamında iki color bildirimi çakıştığında kaynakta sonra gelen black kazanır. MDN, bu kuralı desteklemeyen tarayıcıların iç içe kuralları yanlış sırada ayrıştırabileceğini not eder.
.foo {
background-color: silver;
@media screen {
color: tomato;
}
color: black;
}
/* sıralama: background-color, @media içindeki color, sonra color: black
ekranda iki color çakışır, sonra yazılan black kazanır */Son bir ayrıntı: & işareti iç içe bir stil kuralının dışında kullanılırsa kapsam kökünü (:scope) temsil eder; normal bir stil dosyasında bu belgenin kendisidir. @scope kurallarında kapsam kökü kavramı @scope yazısında anlatılıyor.
Uygulamalı mini örnek: bildirim kutusu bileşeni
MDN'nin bileşik seçici örneğinden uyarladığımız bu bileşen, temel kutu stilini ve uyarı ile başarı varyasyonlarını tek bir kural içinde toplar.
<div class="notice">
<h2 class="notice-heading">Bilgi</h2>
<p>...</p>
</div>
<div class="notice warning">
<h2 class="warning-heading">Uyarı</h2>
<p>...</p>
</div>.notice {
border: black solid 2px;
border-radius: 1rem;
background-color: #ffc107;
color: black;
padding: 1rem;
.notice-heading::before {
/* .notice .notice-heading::before */
content: "i ";
}
&.warning {
/* .notice.warning */
background-color: #d81b60;
border-color: #d81b60;
color: white;
.warning-heading::before {
/* .notice.warning .warning-heading::before */
content: "! ";
}
}
&:hover {
/* .notice:hover */
outline: 2px solid currentcolor;
}
}Örnekte üç farklı iç içe yazım bir arada: .notice-heading::before boşluklu (alt öğe) genişler, &.warning bileşik seçici üretir, &:hover ise öğenin kendi durumunu hedefler. Pseudo-element burada iç kuralın sonunda yer aldığı için sorun yoktur; sınırlama yalnızca & bir pseudo-element'i temsil etmek zorunda kaldığında ortaya çıkar. Özgüllük açısından &.warning 0-2-0, .notice 0-1-0 olduğundan uyarı renkleri temel renkleri geçersiz kılar.
Sık yapılan hatalar

&olmadan pseudo-class yazmak::hovertek başına alt öğeleri hedefler; öğenin kendisi için&:hoveryazın.- Bileşik seçiciyi boşlukla bozmak:
.a { .b {} }.a .bolur;.a.biçin&.bgerekir. - Sass gibi sınıf adı birleştirmeye çalışmak:
&__ogesiyerel CSS'te çalışmaz. - Tür seçicisini
&işaretinden sonra yazmak:&divgeçersizdir,div&yazın. - Seçici listesinin özgüllüğünü hesaba katmamak:
&listedeki en yüksek özgüllüğü taşır. - Pseudo-element kuralının içine iç kural yazmak:
.foo::beforeiçindeki&kuralları ve iç içe at-rule bildirimleri hiçbir şeyle eşleşmez. - Çok derin iç içe yazım: Her düzey seçiciyi uzatır ve özgüllüğü artırır; okunabilirlik için birkaç düzeyle sınırlı kalmak genellikle daha iyidir.
Sık Sorulan Sorular
Yerel CSS nesting kullanmak için Sass gerekir mi?
Hayır. Yerel nesting doğrudan tarayıcı tarafından ayrıştırılır, derleme adımı gerektirmez. Ön işlemcilerin kendi iç içe yazım kuralları ayrı araçların konusudur ve bu yazının kapsamı dışındadır.
& kullanmak zorunlu mu?
Alt öğe ve birleştirici ile başlayan iç kurallarda zorunlu değildir; tarayıcı boşluğu kendisi ekler. Bileşik seçicilerde, pseudo-class'larda ve bağlamı tersine çevirmek istediğinizde zorunludur.
İç içe yazım dosya boyutunu küçültür mü?
MDN, seçicileri tekrar yazmak gerekmediği için iç içe yazımın dosya boyutunu potansiyel olarak azaltabileceğini belirtir. Asıl kazanç okunabilirlik ve bir bileşene ait kuralların tek yerde toplanmasıdır.
@media kuralını seçicinin içine yazınca özgüllük değişir mi?
İç içe at-rule içindeki bildirimler & { ... } içindeymiş gibi davrandığından özgüllük, dış kuralın seçicisiyle aynıdır. Düz yazımda @media içine aynı seçiciyi yazmakla eşdeğerdir.
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 birleştiriciler · Özgüllük hesaplama · :is() ve :where() · @layer · @scope · CSS sözdizimi