CSS @scope kuralı, stillerinizi belgenin belirli bir alt ağacına (DOM subtree) sınırlamanızı sağlar. Bir kapsam kökü (scope root) seçersiniz, isterseniz bir de kapsam sınırı (scope limit) belirlersiniz; blok içindeki seçiciler yalnızca bu iki sınır arasındaki öğeleri hedefler. Böylece .kart > .govde > img gibi uzun, özgüllüğü yüksek ve HTML yapısına sıkı sıkıya bağlı seçiciler yazmadan bileşen düzeyinde stil verebilirsiniz.
Bu yazıda @scope sözdizimini, kök ve sınırın kapsayıcı ya da dışlayıcı oluşunu, :scope sözde sınıfını, kapsamlı kuralların özgüllüğünü ve cascade'e eklenen yakınlık (scoping proximity) ölçütünü örneklerle anlatıyoruz. Cascade'in genel işleyişini cascade ve kalıtım yazısında, özgüllük hesabını özgüllük hesaplama yazısında ayrıntılı bulabilirsiniz.
@scope hangi sorunu çözer?

Bir haber sayfasında article.feature öğesinin içinde section.article-body bulunduğunu, bu bölümde hem doğrudan görseller hem de figure içine yerleştirilmiş görseller olduğunu düşünün. Yalnızca gövde bölümündeki görselleri, ama figure içindekiler hariç, biçimlendirmek istiyorsunuz. Klasik CSS ile iki seçeneğiniz vardır ve ikisi de kusurludur.
.feature > .article-body > imgyazmak: Özgüllüğü yüksektir, sonradan ezmek zorlaşır. Ayrıca HTML yapısı değişirse seçici bozulur..article-body imgyazmak: Daha gevşektir ama bölümün içindeki bütün görselleri,figureiçindekiler dahil, yakalar.
MDN'in örneği tam olarak bu durumu çözer: kapsam kökü olarak .article-body, kapsam sınırı olarak figure verilir. Kural, kökün içindeki görselleri seçer ama sınıra girildiği anda durur.
@scope (.article-body) to (figure) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
/* sonuç: .article-body içindeki img öğeleri çerçeve alır,
figure içindeki img öğeleri etkilenmez */Üst ve alt sınırı olan bu tür kapsama MDN'de donut scope (simit kapsam) adı verilir: ortası boş bir halka gibi, kökten başlayıp sınırda biten bir bölgeyi seçersiniz.
Sözdizimi: iki kullanım biçimi
@scope iki şekilde yazılır. Birincisi stil dosyanızda bağımsız bir bloktur; parantez içindeki seçicilerden oluşan bir prelude (başlangıç bölümü) içerir. İkincisi HTML içindeki bir <style> öğesinde, prelude olmadan yazılan biçimdir; bu durumda kapsam kökü otomatik olarak <style> öğesinin üst öğesi olur.
/* 1. Bağımsız blok: kök ve isteğe bağlı sınır */
@scope (.kart) to (.kart-icerik) {
/* kapsamlı kurallar */
}
/* Yalnızca kök: kökün altındaki her şey */
@scope (.kart) {
/* kapsamlı kurallar */
}<section class="kart">
<style>
@scope {
img { border-radius: 8px; }
}
</style>
<img src="foto.jpg" alt="">
</section>İkinci biçimde de sınır kullanabilirsiniz: @scope to (sınır) { ... } yazımında kök yine üst öğedir, alt sınır ise sizin verdiğiniz seçicidir. Bu satır içi kullanım, sunucu tarafında üretilen bileşenlerde stilin bileşenle birlikte taşınmasını kolaylaştırır; ancak HTML yapısının ayrıntısı bu serinin konusu değildir.
Kök ve sınır birer seçici listesi de olabilir. @scope (.article-hero, .article-body) to (figure) yazdığınızda iki ayrı kapsam tanımlanmış olur ve kural her iki bölümdeki görsellere, figure içindekiler hariç, uygulanır.
Kök kapsayıcı, sınır dışlayıcıdır
Varsayılan davranışta kapsamın üst sınırı (kök) dahildir, alt sınırı ise hariçtir. Yani kök öğenin kendisi kapsamın içindedir, sınır öğesi ve onun altındakiler dışındadır. Bu davranışı değiştirmek için seçicilerden birine evrensel çocuk seçicisi (> *) eklenir. MDN'in verdiği dört kombinasyon şöyledir:
| Yazım | Kök | Sınır |
|---|---|---|
| @scope (kök) to (sınır) | dahil | hariç (varsayılan) |
| @scope (kök) to (sınır > *) | dahil | dahil |
| @scope (kök > *) to (sınır) | hariç | hariç |
| @scope (kök > *) to (sınır > *) | hariç | dahil |
Mantığı şöyle düşünebilirsiniz: kök > * yazdığınızda kapsam kökün kendisinden değil çocuklarından başlar, bu yüzden kök dışarıda kalır. sınır > * yazdığınızda ise kapsam sınırın kendisinde değil çocuklarında biter, bu yüzden sınır öğesinin kendisi içeride kalır.
:scope sözde sınıfı

:scope, seçicilerin eşleştirildiği referans noktasını temsil eder ve hangi öğeyi seçtiği bağlama göre değişir. Stil dosyasının en üst düzeyinde kullanıldığında :root ile aynıdır, yani normal bir HTML belgesinde <html> öğesini seçer. Bir @scope bloğunun içinde ise o bloğun kapsam kökünü seçer. JavaScript tarafında querySelectorAll() gibi DOM yöntemlerinde de kullanılabilir; orada yöntemin çağrıldığı öğeyi temsil eder.
@scope (.feature) {
:scope {
background: rebeccapurple;
color: antiquewhite;
font-family: sans-serif;
}
figure {
background-color: white;
border: 2px solid black;
color: black;
padding: 10px;
}
}
/* sonuç: .feature öğesinin kendisi mor zemin alır,
içindeki figure öğeleri beyaz kutuya dönüşür */:scope sınır seçicisinde de işe yarar. @scope (.article-body) to (:scope > figure) yazdığınızda yalnızca kökün doğrudan çocuğu olan figure öğeleri sınır sayılır; daha derindeki figure öğeleri sınır oluşturmaz. Benzer şekilde to (.feature :scope figure) yazımı, sınırın yalnızca kök bir .feature içindeyken geçerli olmasını sağlar.
@scope içinde özgüllük nasıl hesaplanır?
@scope bloğunun içinde yazdığınız çıplak seçiciler (başında hiçbir şey olmayan img gibi) ve & iç içe yazım seçicisi, başlarına :where(:scope) eklenmiş gibi davranır. :where() sıfır özgüllüğe sahip olduğu için bu görünmez ek ağırlık katmaz; özgüllük seçicinin geri kalanından gelir.
@scope (.article-body) {
/* img: 0-0-1 */
img { border: 2px solid gray; }
/* & img = :where(:scope) img: 0-0-1 */
& img { border-color: black; }
/* :scope img: 0-1-0 + 0-0-1 = 0-1-1 */
:scope img { border-color: goldenrod; }
}
/* sonuç: üç kural da aynı img öğelerini seçer; en yüksek
özgüllük 0-1-1 olduğu için çerçeve rengi goldenrod olur */Adım adım bakalım: img bir tür seçicisidir, değeri 0-0-1'dir. & img yazımında & sıfır ağırlıklı :where(:scope) gibi sayıldığı için sonuç yine 0-0-1'dir. :scope img yazımında ise :scope açıkça yazılmış bir sözde sınıftır ve sınıf düzeyinde 0-1-0 ağırlık ekler; toplam 0-1-1 olur. İlk iki kural eşit özgüllükte olduğu için aralarında kaynak sırası belirleyicidir, ama üçüncü kural ikisini de yener.
Yakınlık: cascade'e eklenen yeni ölçüt
@scope, cascade'e kapsam yakınlığı (scoping proximity) adlı yeni bir ölçüt ekler. İki kapsamdan gelen kurallar çakıştığında, öğeden kapsam köküne DOM ağacında daha az adımla ulaşılan kural kazanır. MDN'in iç içe tema örneği bunu çok iyi gösterir:
<div class="light-theme">
<p>Açık tema</p>
<div class="dark-theme">
<p>Koyu tema</p>
<div class="light-theme">
<p>Yine açık tema</p>
</div>
</div>
</div>.light-theme p { color: black; } ve .dark-theme p { color: white; } gibi klasik kurallarla en içteki paragraf her iki seçiciye de uyar. Özgüllükler eşit olduğu için kaynak sırası karar verir ve sonra yazılan koyu tema kuralı kazanır; paragraf yanlışlıkla beyaz olur. Aynı stilleri @scope ile yazdığınızda durum değişir:
@scope (.light-theme) {
:scope { background: #cccccc; }
p { color: black; }
}
@scope (.dark-theme) {
:scope { background: #333333; }
p { color: white; }
}
/* sonuç: en içteki paragraf siyah olur; .light-theme köküne
1 adım, .dark-theme köküne 2 adım uzaklıktadır */Yakınlığın cascade içindeki yeri önemlidir. MDN'deki sıralamaya göre önce köken ve önem (!important), ardından katmanlar, sonra özgüllük değerlendirilir; yakınlık yalnızca bunlar eşit olduğunda devreye girer ve kaynak sırasından önce gelir. Yani daha özgül bir seçici, daha uzak bir kapsamdan gelse bile yakın kapsamdaki daha az özgül kuralı yener. Katmanların etkisi için @layer cascade katmanları yazısına bakabilirsiniz.
Kapsam kalıtımı durdurmaz
@scope seçicilerin hangi öğelere ulaşacağını sınırlar, ama uygulanan stilleri tamamen yalıtmaz. En belirgin fark kalıtımda görülür: color ya da font-family gibi kalıtılan özellikler kapsam sınırını aşarak alt öğelere geçmeye devam eder. Örneğin kökte color: antiquewhite verdiyseniz, sınırın altındaki figure da bu rengi kalıtır; sınır yalnızca kapsamlı kuralların doğrudan seçim yapmasını engeller. Bu yüzden yukarıdaki örnekte figure öğesine ayrıca color: black verilmiştir.
Mini örnek: kendi içinde tutarlı bir kart bileşeni
Bir kart bileşeninin başlığını ve bağlantılarını biçimlendirmek, ama kartın içine yerleştirilebilen başka bir bileşenin (örneğin .yorumlar) içine karışmamak istediğinizi düşünün:
@scope (.kart) to (.yorumlar) {
:scope {
padding: 1rem;
border: 1px solid #dddddd;
}
h2 { font-size: 1.25rem; }
a { color: darkmagenta; }
}
/* sonuç: kartın kendisi çerçeve ve iç boşluk alır;
kart içindeki h2 ve a öğeleri biçimlenir;
.yorumlar ve altındaki h2 ile a öğeleri bu kurallardan etkilenmez */Bu yaklaşımın üç avantajı vardır. Birincisi, h2 ve a kuralları yalnızca 0-0-1 özgüllüğe sahiptir; başka bir yerde sınıfla ezmek kolaydır. İkincisi, kartın HTML yapısı değişse bile (örneğin başlık bir header içine taşınsa) kural çalışmaya devam eder. Üçüncüsü, yorumlar bölümü kendi kurallarını yazarken kart stilleriyle yarışmak zorunda kalmaz. Ancak yorumlar bölümü kartın color değerini kalıtım yoluyla almaya devam eder.
@scope, iç içe yazım ve @layer karşılaştırması

| Araç | Ne yapar | Özgüllüğe etkisi |
|---|---|---|
| @scope | Seçimi bir alt ağaçla sınırlar, alt sınır koyabilir | Kök seçicisi eklenmez; :scope açıkça yazılırsa 0-1-0 ekler |
| İç içe yazım (nesting) | Seçicileri üst seçiciye bağlı yazmayı sağlar | Üst seçicinin özgüllüğü iç seçiciye eklenir |
| @layer | Kuralları öncelik katmanlarına ayırır | Özgüllüğü değiştirmez, ondan önce değerlendirilir |
| Uzun alt seçici | Yapıya bağlı seçim yapar | Her parça özgüllüğü artırır |
Bu araçlar birbirinin yerine geçmez, birlikte kullanılabilir. İç içe yazımın özgüllük etkisi için CSS nesting yazısına bakabilirsiniz. @layer hangi stil grubunun genel olarak öncelikli olduğunu, @scope ise bir kuralın belgenin neresinde geçerli olduğunu belirler.
Ne zaman @scope kullanmak mantıklıdır?
Her stil için kapsam açmanız gerekmez. Tek bir öğeyi biçimlendiren basit bir sınıf seçicisi çoğu zaman yeterlidir. @scope asıl şu durumlarda fayda sağlar: aynı bileşen sayfada birden fazla yerde ve farklı derinliklerde kullanılıyorsa, bir bileşenin içine başka bir bileşen yerleştirilebiliyorsa (alt sınır burada devreye girer), açık ve koyu gibi temalar iç içe geçebiliyorsa (yakınlık burada devreye girer) ya da bir bileşenin iç öğelerine sınıf eklemek pratik değilse. Son durumda h2, p, img gibi tür seçicilerini kapsam içinde güvenle kullanabilirsiniz; çünkü kurallar kökün dışına taşmaz ve düşük özgüllükleri sayesinde gerektiğinde kolayca ezilebilir.
Sık yapılan hatalar
- Sınırın da biçimleneceğini sanmak: Varsayılan olarak sınır öğesi kapsam dışındadır. Sınırın kendisini dahil etmek için
to (sınır > *)yazın. - Kalıtımın da kesileceğini beklemek: Kalıtılan özellikler sınırı aşar. Sınırın altındaki öğe için gerekiyorsa değeri açıkça yeniden verin.
- Yakınlığın özgüllüğü yeneceğini sanmak: Yakınlık özgüllükten sonra gelir. Uzaktaki ama daha özgül bir kural yine kazanır.
- Kardeşi kapsamdan seçmeye çalışmak:
:scope + pgibi seçiciler hiçbir zaman eşleşmez. - Kök seçicisini özgüllüğe eklemek:
@scope (.article-body) { img {} }içindekiimgkuralı 0-1-1 değil 0-0-1 değerindedir.
Sık Sorulan Sorular
@scope ile Shadow DOM aynı şey mi?
Hayır. MDN'e göre @scope seçicilerin hangi alt ağaçta eşleşeceğini sınırlar ama uygulanan stilleri tam olarak yalıtmaz; kalıtılan özellikler sınırı aşar ve kapsam dışındaki genel kurallar kapsamın içindeki öğelere de uygulanabilir.
:scope ile :root arasındaki fark nedir?
Stil dosyasının en üst düzeyinde ikisi aynı öğeyi, yani <html> öğesini seçer. @scope bloğu içinde ise :scope o bloğun kapsam kökünü seçer; :root yine belge köküdür.
Aynı öğe için iki @scope bloğu çakışırsa hangisi kazanır?
Önce köken, önem, katman ve özgüllük karşılaştırılır. Bunlar eşitse öğeye DOM ağacında daha yakın olan kapsam kökünün kuralı kazanır. Yakınlık da eşitse kaynakta sonra gelen kural uygulanır.
@scope bloğu içinde & kullanabilir miyim?
Evet. &, başına :where(:scope) eklenmiş gibi davranır ve özgüllüğe ağırlık katmaz. Ancak MDN, bu davranışın tarayıcı motoruna ve sürümüne göre farklılık gösterebildiğini belirtir; uyumluluk tablosunu kontrol edin.
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 · Özgüllük hesaplama · @layer · CSS nesting · :is(), :where(), :has()