Gölge DOM 201

CSS ve stil

Bu makalede, Gölge DOM ile yapabileceğiniz diğer muhteşem şeyler anlatılmaktadır. Bu sürüm, Gölge DOM 101'de açıklanan kavramları temel alır. Bir tanıtım metni arıyorsanız o makaleye bakın.

Giriş

Kabul edelim. Stilsiz işaretlemenin hoşuna gidecek bir şey yoktur. Neyse ki Web Bileşenleri'nin arkasındaki yetenekli çalışanlar bu durumu önceden tahmin ederek bizi beklemeye devam etmedi. CSS Kapsam Oluşturma Modülü, bir gölge ağacında içeriğin stilini belirlemek için birçok seçenek tanımlar.

Stil kapsülleme

Gölge DOM'un temel özelliklerinden biri gölge sınırıdır. Birçok güzel özelliği var, ancak en iyi özelliklerinden biri ücretsiz stil kapsüllemesi sunması. Başka bir ifadeyle:

<div><h3>Light DOM</h3></div>
<script>
var root = document.querySelector('div').createShadowRoot();
root.innerHTML = `
  <style>
    h3 {
      color: red;
    }
  </style>
  <h3>Shadow DOM</h3>
`;
</script>

Bu demoyla ilgili iki ilginç gözlem var:

  • Bu sayfada başka h3'ler de vardır ancak h3 seçicisiyle eşleşen, dolayısıyla kırmızıyla eşleşen tek öğe ShadowRoot'takidir. Stiller varsayılan olarak sınırlandırıldı.
  • Bu sayfada tanımlanan ve h3'leri hedefleyen diğer stil kuralları içeriğime akmıyor. Bunun nedeni, seçicilerin gölge sınırını geçmemesidir.

Hikayenin moralini biliyor musunuz? Dış dünyadan stil kapsülleme yapıyoruz. Shadow DOM'ye teşekkürler!

Barındırma öğesinin stilini belirleme

:host, gölge ağacı barındıran öğeyi seçmenize ve biçimlendirmenize olanak tanır:

<button class="red">My Button</button>
<script>
var button = document.querySelector('button');
var root = button.createShadowRoot();
root.innerHTML = `
  <style>
    :host {
      text-transform: uppercase;
    }
  </style>
  <content></content>
`;
</script>

İyi bir fikir, üst sayfadaki kuralların öğede tanımlanan :host kurallarından daha yüksek spesifikliğe, barındırma öğesinde tanımlanan style özelliğinden daha düşük spesifikliğe sahip olmasıdır. Bu, kullanıcıların stilinizi dışarıdan geçersiz kılmasına olanak tanır. :host, yalnızca ShadowRoot bağlamında da çalıştığından Shadow DOM dışında kullanılamaz.

:host(<selector>) öğesinin işlevsel biçimi, bir <selector> ile eşleşmesi durumunda barındırma öğesini hedeflemenize olanak tanır.

Örnek - yalnızca öğenin kendisi .different sınıfına (ör. <x-foo class="different"></x-foo>) sahipse eşleşme:

:host(.different) {
    ...
}

Kullanıcı durumlarına tepki verme

Özel Öğe oluştururken ve farklı kullanıcı durumlarına (:hover, :focus, :active vb.) tepki vermek istediğinizde :host sık kullanılır.

<style>
  :host {
    opacity: 0.4;
    transition: opacity 420ms ease-in-out;
  }
  :host(:hover) {
    opacity: 1;
  }
  :host(:active) {
    position: relative;
    top: 3px;
    left: 3px;
  }
</style>

Öğelere tema oluşturma

:host-context(<selector>) sözde sınıfı, barındırma öğesiyle veya üst öğelerinden herhangi biri <selector> ile eşleşirse eşleşir.

:host-context() özelliğinin yaygın bir kullanımı, bir öğeyi çevreleyen çevresine göre tema eklenmesidir. Örneğin, birçok kişi <html> veya <body> için bir sınıf uygulayarak tema oluşturuyor:

<body class="different">
  <x-foo></x-foo>
</body>

.different sınıfına sahip bir öğenin alt öğesi olduğunda <x-foo> stilini belirlemek için :host-context(.different):

:host-context(.different) {
  color: red;
}

Bu size, bir öğenin Gölge DOM'unda, bağlamına göre öğeyi benzersiz şekilde biçimlendiren stil kurallarını kapsülleme imkanı sunar.

Tek bir gölge kökünden birden fazla ana makine türünü destekleme

:host özelliğinin bir başka kullanımı da bir tema kitaplığı oluşturuyor ve aynı Gölge DOM'den birçok ana makine öğesi türünün stilini oluşturmayı desteklemek istemenizdir.

:host(x-foo) {
    /* Applies if the host is a <x-foo> element.*/
}

:host(x-foo:host) {
    /* Same as above. Applies if the host is a <x-foo> element. */
}

:host(div) {
    /* Applies if the host element is a <div>. */
}

Gölge DOM dahili öğelerinin stilini dışarıdan belirleme

::shadow sözde öğe ve /deep/ kombinasyonu, CSS otoritesinin Vorpal kılıcına sahip olmaya benzer. Gölge ağaçları içinde öğelerin stilini belirlemek için Gölge DOM'un sınırında delme işlemi yapılmasını sağlarlar.

::shadow sözde öğe

Bir öğenin en az bir gölge ağacı varsa ::shadow sözde öğesi, gölge köküyle eşleşir. Düğümleri bir öğenin gölge alanının içinde biçimlendiren seçiciler yazmanıza olanak tanır.

Örneğin, bir öğe gölge kökü barındırıyorsa gölge ağacındaki tüm kapsamların stilini belirlemek için #host::shadow span {} yazabilirsiniz.

<style>
  #host::shadow span {
    color: red;
  }
</style>

<div id="host">
  <span>Light DOM</span>
</div>

<script>
  var host = document.querySelector('div');
  var root = host.createShadowRoot();
  root.innerHTML = `
    <span>Shadow DOM</span>
    <content></content>
  `;
</script>

Örnek (özel öğeler) - <x-tabs>, Gölge DOM'da <x-panel> alt öğesine sahip. Her panel, h2 başlık içeren kendi gölge ağacını barındırır. Ana sayfadaki bu başlıkların stilini belirlemek için şöyle yazılabilir:

x-tabs::shadow x-panel::shadow h2 {
    ...
}

/deep/ Kombinatörü

/deep/ kombinasyonu ::shadow ile benzerdir, ancak daha güçlüdür. Tüm gölge sınırlarını tamamen yok sayar ve istenilen sayıda gölge ağaçla kesişir. Basitçe söylemek gerekirse /deep/, bir öğenin bağırsaklarını incelemenize ve herhangi bir düğümü hedeflemenize olanak tanır.

/deep/ kombinasyonu, birden çok Gölge DOM düzeyinin yaygın olarak kullanıldığı Özel Öğeler dünyasında özellikle kullanışlıdır. Birincil örnekler, bir grup özel öğeyi iç içe yerleştirmek (her biri kendi gölge ağacını barındırır) veya <shadow> kullanarak başka bir öğeden devralan bir öğe oluşturmaktır.

Örnek (özel öğeler) - ağacın herhangi bir yerinde <x-tabs> etiketinin alt öğesi olan tüm <x-panel> öğelerini seçin:

x-tabs /deep/ x-panel {
    ...
}

Örnek - gölge ağacında herhangi bir yerde, tüm öğelerin stilini .library-theme sınıfıyla belirleyin:

body /deep/ .library-theme {
    ...
}

querySelector() ile çalışma

.shadowRoot'in DOM geçişi için gölge ağaçlarını açması gibi, birleştiriciler de seçici geçişi için gölge ağaçlarını açar. İç içe geçmiş bir çılgınlık zinciri yazmak yerine tek bir ifade yazabilirsiniz:

// No fun.
document.querySelector('x-tabs').shadowRoot
        .querySelector('x-panel').shadowRoot
        .querySelector('#foo');

// Fun.
document.querySelector('x-tabs::shadow x-panel::shadow #foo');

Yerel öğelerin stilini belirleme

Yerel HTML denetimleri, stil oluşturmak için zorlu bir süreçtir. Pek çok kişi vazgeçer ve kendini yuvarlar. Bununla birlikte, ::shadow ve /deep/ ile web platformunda Gölge DOM kullanan tüm öğelerin stili ayarlanabilir. <input> türleri ve <video> en iyi örnekler arasındadır:

video /deep/ input[type="range"] {
  background: hotpink;
}

Stil kancaları oluşturma

Özelleştirme iyidir. Bazı durumlarda Gölge'nizin kalkanında delikler açmak ve başkalarının tarzını belirleyecek kancalar oluşturmak isteyebilirsiniz.

::shadow ve /deep/ ifadelerini kullanma

/deep/, arkanızda çok fazla güç vardır. Bileşen yazarlarına, bağımsız öğeleri stile uygun veya çok sayıda öğeyi temaya uygun olarak tanımlamaları için bir yol sunar.

Örnek - tüm gölge ağaçlarını yok sayarak .library-theme sınıfına sahip tüm öğelerin stilini belirleyin:

body /deep/ .library-theme {
    ...
}

Özel sözde öğeleri kullanma

Hem WebKit hem de Firefox, yerel tarayıcı öğelerinin dahili parçalarını biçimlendirmek için yapay öğeleri tanımlar. Buna iyi bir örnek input[type=range] olabilir. Kaydırma çubuğu küçük resmini, <span style="color:blue">blue</span> stilini ::-webkit-slider-thumb hedefleyerek biçimlendirebilirsiniz:

input[type=range].custom::-webkit-slider-thumb {
  -webkit-appearance: none;
  background-color: blue;
  width: 10px;
  height: 40px;
}

Tarayıcıların bazı dahili öğelere stil kancaları sağlamasına benzer şekilde, Gölge DOM içeriğinin yazarları belirli öğelerin dışarıdan kişiler tarafından şekillendirilebilecek şekilde belirtilmesini sağlayabilir. Bu işlem, özel sözde öğeler aracılığıyla yapılır.

pseudo özelliğini kullanarak bir öğeyi özel bir sözde öğe olarak tanımlayabilirsiniz. Değerinin veya adının önüne "x-" eklenmesi gerekir. Bunu yaptığınızda, gölge ağacında söz konusu öğeyle bir ilişkilendirme oluşturulur ve yabancılara gölge sınırını geçmeleri için özel bir şerit verilir.

Özel bir kaydırma çubuğu widget'ı oluşturmaya ve kullanıcıların kaydırma çubuğu baş parmağının mavi stilini belirlemesine izin vermeye ilişkin bir örneği burada bulabilirsiniz:

<style>
  #host::x-slider-thumb {
    background-color: blue;
  }
</style>
<div id="host"></div>
<script>
  var root = document.querySelector('#host').createShadowRoot();
  root.innerHTML = `
    <div>
      <div pseudo="x-slider-thumb"></div>' +
    </div>
  `;
</script>

CSS Değişkenlerini Kullanma

Tema kancaları oluşturmanın etkili bir yolu, CSS Değişkenleri kullanmaktır. Esas olarak, diğer kullanıcıların dolduracağı "stil yer tutucuları" oluşturmak.

Gölge DOM'larındaki değişken yer tutucuları işaretleyen bir özel öğe yazarı düşünün. Biri dahili bir düğmenin yazı tipini şekillendirmek için, diğeri rengi için:

button {
  color: var(--button-text-color, pink); /* default color will be pink */
  font-family: var(--button-font);
}

Ardından, öğenin yerleştiricisi bu değerleri istedikleri şekilde tanımlar. Belki kendi sayfalarının harika Comic Sans temasına uyar:

#host {
  --button-text-color: green;
  --button-font: "Comic Sans MS", "Comic Sans", cursive;
}

CSS Değişkenlerinin devralma biçimi sayesinde her şey çok daha iyidir ve çok güzel çalışır. Resmin tamamı aşağıdaki gibi görünür:

<style>
  #host {
    --button-text-color: green;
    --button-font: "Comic Sans MS", "Comic Sans", cursive;
  }
</style>
<div id="host">Host node</div>
<script>
  var root = document.querySelector('#host').createShadowRoot();
  root.innerHTML = `
    <style>
      button {
        color: var(--button-text-color, pink);
        font-family: var(--button-font);
      }
    </style>
    <content></content>
  `;
</script>

Stiller sıfırlanıyor

Yazı tipleri, renkler ve çizgi yükseklikleri gibi devralınabilir stiller, Gölge DOM'daki öğeleri etkilemeye devam eder. Ancak maksimum esneklik sağlamak amacıyla Gölge DOM, gölge sınırında ne olacağını kontrol etmemiz için bize resetStyleInheritance özelliğini sağlar. Bunu, yeni bir bileşen oluştururken yeni bir başlangıç yapmanın bir yolu olarak düşünebilirsiniz.

resetStyleInheritance

Aşağıda, resetStyleInheritance değişikliğinin gölge ağacını nasıl etkilediğini gösteren bir demo bulunmaktadır:

<div>
  <h3>Light DOM</h3>
</div>

<script>
  var root = document.querySelector('div').createShadowRoot();
  root.resetStyleInheritance = <span id="code-resetStyleInheritance">false</span>;
  root.innerHTML = `
    <style>
      h3 {
        color: red;
      }
    </style>
    <h3>Shadow DOM</h3>
    <content select="h3"></content>
  `;
</script>

<div class="demoarea" style="width:225px;">
  <div id="style-ex-inheritance"><h3 class="border">Light DOM</div>
</div>
<div id="inherit-buttons">
  <button id="demo-resetStyleInheritance">resetStyleInheritance=false</button>
</div>

<script>
  var container = document.querySelector('#style-ex-inheritance');
  var root = container.createShadowRoot();
  //root.resetStyleInheritance = false;
  root.innerHTML = '<style>h3{ color: red; }</style><h3>Shadow DOM<content select="h3"></content>';

  document.querySelector('#demo-resetStyleInheritance').addEventListener('click', function(e) {
    root.resetStyleInheritance = !root.resetStyleInheritance;
    e.target.textContent = 'resetStyleInheritance=' + root.resetStyleInheritance;
    document.querySelector('#code-resetStyleInheritance').textContent = root.resetStyleInheritance;
  });
</script>
Geliştirici Araçları&#39;ndan devralınan özellikler

.resetStyleInheritance öğesini anlamak, özellikle devralınabilen CSS mülkleri üzerinde etkisi olduğundan biraz daha zordur. Şöyle diyor: Devralacak bir mülk ararken, sayfa ile ShadowRoot arasındaki sınırda ana makineden değer devralmayın, bunun yerine initial değerini kullanın (CSS spesifikasyonuna göre).

Hangi özelliklerin CSS'de devraldığından emin değilseniz bu kullanışlı listeye göz atın veya Öğe panelinde "Devralınanı göster" onay kutusunu değiştirin.

Dağıtılmış düğümlerin stil özelliklerini ayarlama

Dağıtılmış düğümler, bir ekleme noktasında (bir <content> öğesi) oluşturulan öğelerdir. <content> öğesi, Işık DOM'sinden düğüm seçmenize ve bunları Gölge DOM'unuzda önceden tanımlanmış konumlarda oluşturmanıza olanak tanır. Mantıksal olarak Gölge DOM'de yer almazlar; hâlâ barındıran öğenin alt öğeleridirler. Ekleme noktaları, yalnızca oluşturma aşamasından ibarettir.

Dağıtılan düğümler ana dokümandaki stilleri korur. Yani ana sayfadaki stil kuralları, ekleme noktasında oluşturulduklarında bile öğelere uygulanmaya devam eder. Burada da dağıtılmış düğümler mantıksal olarak ışık domimi içindedir ve hareket etmez. Bunlar başka bir yerde oluşturulur. Ancak, düğümler Gölge DOM'a dağıtıldığında, gölge ağacı içinde tanımlanan ek stilleri kullanabilirler.

::içerik sözde öğe

Dağıtılan düğümler ana makine öğesinin alt öğeleridir. Öyleyse bunları Gölge DOM'un içinden nasıl hedefleyebiliriz? Yanıt, CSS ::content sözde öğesidir. Bu yöntem, bir ekleme noktasından geçen Işık DOM düğümlerini hedeflemenin bir yoludur. Örneğin:

::content > h3, bir ekleme noktasından geçen tüm h3 etiketlerinin stilini belirler.

Bir örnek verelim:

<div>
  <h3>Light DOM</h3>
  <section>
    <div>I'm not underlined</div>
    <p>I'm underlined in Shadow DOM!</p>
  </section>
</div>

<script>
var div = document.querySelector('div');
var root = div.createShadowRoot();
root.innerHTML = `
  <style>
    h3 { color: red; }
      content[select="h3"]::content > h3 {
      color: green;
    }
    ::content section p {
      text-decoration: underline;
    }
  </style>
  <h3>Shadow DOM</h3>
  <content select="h3"></content>
  <content select="section"></content>
`;
</script>

Ekleme noktalarındaki stiller sıfırlanıyor

Bir ShadowRoot oluştururken, devralınan stilleri sıfırlama seçeneğiniz vardır. <content> ve <shadow> kampanya noktasında da bu seçenek var. Bu öğeleri kullanırken ya JS'de .resetStyleInheritance özelliğini ayarlayın ya da öğenin kendisinde boole reset-style-inheritance özelliğini kullanın.

  • ShadowRoot veya <shadow> ekleme noktaları için: reset-style-inheritance, devralınabilir CSS mülklerinin gölge içeriğinize ulaşmadan önce ana makinede initial olarak ayarlandığı anlamına gelir. Bu konum, üst sınır olarak bilinir.

  • <content> kampanya noktaları için: reset-style-inheritance, ana makinenin alt öğelerinin ekleme noktasında dağıtılmadan önce devralınabilir CSS özelliklerinin initial olarak ayarlanması anlamına gelir. Bu konum, alt sınır olarak bilinir.

Sonuç

Özel öğelerin yazarları olarak, içeriğimizin görünümünü ve tarzını kontrol etmek için sayısız seçenek sunuyoruz. Gölge DOM, bu cesur yeni dünyanın temelini oluşturuyor.

Gölge DOM, bize kapsamlı stil kapsüllemesi ve seçimlerimiz doğrultusunda dış dünyaya izin vermemizi sağlayacak bir araç sunar. Yazarlar, özel sözde öğeler tanımlayarak veya CSS Değişkeni yer tutucuları ekleyerek üçüncü taraflara içeriklerini daha da özelleştirmek için kullanışlı stil kancaları sağlayabilir. Sonuç olarak, içeriklerinin nasıl temsil edileceği konusunda tam denetim web yazarlarının elindedir.