Paylaşılan Stil Sayfası Kullanarak Web Bileşenlerini Şekillendirme

Yayınlanan: 2022-03-10
Hızlı özet ↬ Web bileşenleri, web'in harika bir yeni özelliğidir ve geliştiricilerin kendi özel HTML öğelerini tanımlamalarına olanak tanır. Web bileşenleri, bir stil kılavuzuyla birleştirildiğinde, geliştiricilerin kod parçacıklarını kopyalamayı ve yapıştırmayı bırakmasına ve bunun yerine yalnızca bir DOM öğesi kullanmasına olanak tanıyan bir bileşen API'si oluşturabilir. Gölge DOM'yi kullanarak, web bileşenini kapsülleyebiliriz ve sayfadaki başka herhangi bir stil sayfasıyla özgüllük savaşları konusunda endişelenmemize gerek kalmaz. Ancak, web bileşenleri ve stil kılavuzları şu anda birbiriyle çelişiyor gibi görünüyor.

Web bileşenleri, web'in harika bir yeni özelliğidir ve geliştiricilerin kendi özel HTML öğelerini tanımlamalarına olanak tanır. Web bileşenleri, bir stil kılavuzuyla birleştirildiğinde, geliştiricilerin kod parçacıklarını kopyalamayı ve yapıştırmayı bırakmasına ve bunun yerine yalnızca bir DOM öğesi kullanmasına olanak tanıyan bir bileşen API'si oluşturabilir. Gölge DOM'yi kullanarak, web bileşenini kapsülleyebiliriz ve sayfadaki başka herhangi bir stil sayfasıyla özgüllük savaşları konusunda endişelenmemize gerek kalmaz.

Ancak, web bileşenleri ve stil kılavuzları şu anda birbiriyle çelişiyor gibi görünüyor. Bir yandan, stil kılavuzları, sayfaya küresel olarak uygulanan ve web sitesi genelinde tutarlılığı sağlayan bir dizi kural ve stil sağlar. Öte yandan, gölge DOM'ye sahip web bileşenleri, küresel stillerin kapsüllemelerine nüfuz etmesini engeller ve böylece stil kılavuzunun onları etkilemesini önler.

SmashingMag'de Daha Fazla Okuma :

  • Bileşen Tabanlı Sistemlerde En İyi Uygulamaları Zorlama
  • Daha Akıllı Stil Sayfaları İçin LESS CSS Ön İşlemcisi Nasıl Kullanılır
  • Adobe Edge Reflow'a Derin Bir Bakış

Peki, gölge DOM'lu web bileşenlerine bile tutarlılık ve stiller sağlamaya devam eden global stil kılavuzlarıyla bu ikisi nasıl bir arada var olabilir? Neyse ki, bugün işe yarayan çözümler var ve küresel stil kılavuzlarının web bileşenlerine stil sağlamasını sağlayan daha fazla çözüm var. (Bu makalenin geri kalanında, gölge DOM'ye sahip özel öğelere atıfta bulunmak için "web bileşenleri" terimini kullanacağım.)

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Bir Web Bileşeninde Global Stil Kılavuzu Stili Ne Olmalı?

Bir web bileşenine stil vermek için küresel bir stil kılavuzunun nasıl alınacağını tartışmadan önce, neyin stillendirmeye çalışıp ne yapmaması gerektiğini tartışmalıyız.

Her şeyden önce, web bileşenleri için mevcut en iyi uygulamalar, stilleri de dahil olmak üzere bir web bileşeninin, çalışması için herhangi bir dış kaynağa bağlı olmaması için kapsüllenmesi gerektiğini belirtir. Bu, stil kılavuzu mevcut olmadığında bile web sitesinde veya dışında herhangi bir yerde kullanılmasına izin verir.

Aşağıda, tüm stillerini kapsayan basit bir oturum açma formu web bileşeni bulunmaktadır.

 <template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } p { margin: 0; } p + p { margin-top: 20px; } a { color: #1f66e5; } label { display: block; margin-bottom: 5px; } input[type="text"], input[type="password"] { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } input[type="submit"] { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <div class="container"> <form action="#"> <p> <label for="username">User Name</label> <input type="text" name="username"> </p> <p> <label for="password">Password</label> <input type="password" name="password"> </p> <p> <input type="submit" value="Login"> </p> <p class="footnote">Not registered? <a href="#">Create an account</a></p> </form> </div> </template> <script> const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); const root = this.attachShadow({mode: 'closed'}); const temp = document.importNode(template.content, true); root.appendChild(temp); } }); </script>

Not: Kod örnekleri, web bileşenleri için sürüm 1 belirtiminde yazılmıştır.

Kullanıcı adı ve şifre ile giriş formu.
Basit bir oturum açma formu web bileşeni

Bununla birlikte, her web bileşenini tam olarak kapsüllemek, özellikle de yerel öğelerin tipografisini ve stilini ayarlamak söz konusu olduğunda, kaçınılmaz olarak çok sayıda yinelenen CSS'ye yol açacaktır. Bir geliştirici, web bileşenlerinde bir paragraf, bağlantı etiketi veya giriş alanı kullanmak isterse, web sitesinin geri kalanı gibi biçimlendirilmelidir.

Web bileşeninin ihtiyaç duyduğu tüm stilleri tam olarak kapsüllersek, paragrafları, bağlantı etiketlerini, giriş alanlarını vb. biçimlendirmek için CSS, bunları kullanan tüm web bileşenlerinde çoğaltılır. Bu, yalnızca bakım maliyetlerini artırmakla kalmayacak, aynı zamanda kullanıcılar için çok daha büyük indirme boyutlarına da yol açacaktır.

Tüm stilleri kapsüllemek yerine, web bileşenleri yalnızca benzersiz stillerini kapsamalı ve ardından diğer her şey için stilleri işlemek için bir dizi paylaşılan stile bağlı olmalıdır. Bu paylaşılan stiller, esasen, web bileşenlerinin yerel öğelerin stil kılavuzuna göre biçimlendirilmesini sağlamak için kullanabileceği bir tür Normalize.css haline gelecektir.

Önceki örnekte, oturum açma formu web bileşeni, yalnızca iki benzersiz sınıfı için stilleri bildirir: .container ve .footnote . Stillerin geri kalanı paylaşılan stil sayfasına ait olacak ve paragrafları, bağlantı etiketlerini, giriş alanlarını vb. biçimlendirecektir.

Kısacası, stil kılavuzu web bileşenine stil vermeye çalışmamalı, bunun yerine web bileşenlerinin tutarlı bir görünüm elde etmek için kullanabileceği bir dizi paylaşılan stil sağlamalıdır.

Shadow DOM'u Harici Stil Sayfalarıyla Şekillendirme Eskiden Nasıl Yapılırdı?

Web bileşenleri için ilk belirtim (sürüm 0 olarak bilinir), herhangi bir harici stil sayfasının ::shadow veya /deep/ CSS seçicilerini kullanarak gölge DOM'ye girmesine izin verdi. ::shadow ve /deep/ kullanımı, web bileşeni istese de istemese de, gölge DOM'ye nüfuz eden bir stil kılavuzuna sahip olmanızı ve paylaşılan stilleri ayarlamanızı sağladı.

 /* Style all p tags inside a web components shadow DOM */ login-form::shadow p { color: red; }

Web bileşenleri belirtiminin en yeni sürümünün (sürüm 1 olarak bilinir) ortaya çıkmasıyla birlikte, yazarlar harici stil sayfalarının gölge DOM'ye nüfuz etme yeteneğini kaldırdılar ve hiçbir alternatif sunmadılar. Bunun yerine, felsefe, ejderha kullanmaktan web bileşenlerine stil vermek yerine köprüleri kullanmaya değişti. Başka bir deyişle, web bileşeni yazarları, bileşenlerine izin vermeye zorlanmak yerine, hangi harici stil kurallarına izin verildiğinden sorumlu olmalıdır.

Ne yazık ki, bu felsefe henüz internete tam olarak yetişemedi, bu da bizi biraz zor durumda bırakıyor. Neyse ki, bugün mevcut olan ve bazıları çok da uzak olmayan bir gelecekte sunulacak olan birkaç çözüm, paylaşılan bir stil sayfasının bir web bileşenine stil vermesini sağlayacaktır.

Bugün Yapabilecekleriniz

Bir web bileşeninin stilleri paylaşmasına izin verecek bugün kullanabileceğiniz üç teknik vardır: @import , özel öğeler ve bir web bileşeni kitaplığı.

@import kullanma

Bugün bir web bileşenine stil sayfası getirmenin tek yerel yolu @import kullanmaktır. Bu işe yarasa da, bir anti-kalıptır. Ancak web bileşenleri için bu daha da büyük bir performans sorunudur.

 <template> <style> @import "styleguide.css" </style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>

Normalde, @import bir anti-kalıptır çünkü tüm stil sayfalarını paralel yerine seri olarak, özellikle de iç içe geçmişlerse indirir. Bizim durumumuzda, seri halinde tek bir stil sayfası indirmek yardımcı olamaz, bu nedenle teoride sorun olmaz. Ancak bunu Chrome'da test ettiğimde, sonuçlar @import kullanmanın sayfanın, stilleri doğrudan web bileşenine gömmeye kıyasla yarım saniyeye kadar daha yavaş oluşturulmasına neden olduğunu gösterdi.

Not: HTML içe aktarmalarının çoklu dolgusunun yerel HTML içe aktarmalarına kıyasla çalışma biçimindeki farklılıklar nedeniyle, WebPagetest.org yalnızca HTML içe aktarmalarını yerel olarak destekleyen tarayıcılarda (yani Chrome) güvenilir sonuçlar vermek için kullanılabilir.

Yerel web bileşeni performansının çubuk grafiği.
Üç performans testinden elde edilen sonuçlar, @import tarayıcının, stilleri doğrudan web bileşenine gömmeye kıyasla yarım saniyeye kadar daha yavaş işlemesine neden olduğunu gösteriyor.

Sonunda, @import hala bir anti-kalıptır ve web bileşenlerinde bir performans sorunu olabilir. Yani, harika bir çözüm değil.

Gölge DOM'yi Kullanmayın

Web bileşenlerine paylaşılan stiller sağlamaya çalışmanın sorunu, gölge DOM'nin kullanılmasından kaynaklandığından, sorunu tamamen önlemenin bir yolu, gölge DOM'yi kullanmamaktır.

Gölge DOM'yi kullanmadığınızda, web bileşenleri yerine özel öğeler oluşturacaksınız (aşağıya bakın), tek fark gölge DOM'nin olmaması ve kapsam belirlemedir. Öğeniz sayfanın stillerine tabi olacak, ancak bugün bununla zaten uğraşmak zorundayız, bu yüzden nasıl başa çıkacağımızı bilmediğimiz bir şey değil. Özel öğeler, harika tarayıcı desteğine sahip webcomponentjs polyfill tarafından tam olarak desteklenir.

Özel öğelerin en büyük yararı, bugün bunları kullanarak bir desen kitaplığı oluşturabilmeniz ve paylaşılan stil sorunu çözülene kadar beklemeniz gerekmemesidir. Ve web bileşenleri ile özel öğeler arasındaki tek fark gölge DOM olduğundan, paylaşılan stil için bir çözüm mevcut olduğunda, özel öğelerinizde gölge DOM'yi her zaman etkinleştirebilirsiniz.

Özel öğeler oluşturmaya karar verirseniz, özel öğeler ve web bileşenleri arasındaki birkaç farklılığın farkında olun.

İlk olarak, özel öğenin stilleri sayfa stillerine tabi olduğundan ve bunun tersi de geçerlidir, seçicilerinizin herhangi bir çakışmaya neden olmadığından emin olmak isteyeceksiniz. Sayfalarınız zaten bir stil kılavuzu kullanıyorsa, özel öğenin stillerini stil kılavuzunda bırakın ve öğenin beklenen DOM ve sınıf yapısını çıkarmasını sağlayın.

Stilleri stil kılavuzunda bırakarak, geliştiricileriniz için sorunsuz bir geçiş yolu oluşturacaksınız, çünkü onlar stil kılavuzunu daha önce olduğu gibi kullanmaya devam edebilirler, ancak daha sonra, mümkün olduğunda yavaş yavaş yeni özel öğeyi kullanmaya geçebilirler. Herkes özel öğeyi kullandığında, stilleri bir arada tutmak ve daha sonra web bileşenlerinde daha kolay yeniden düzenlemeye izin vermek için öğenin içinde kalacak şekilde taşıyabilirsiniz.

İkinci olarak, herhangi bir değişkeni global kapsamda boşaltmamak için herhangi bir JavaScript kodunu hemen çağrılan bir işlev ifadesinin (IFFE) içine yerleştirdiğinizden emin olun. CSS kapsamı sağlamamaya ek olarak, özel öğeler JavaScript kapsamı sağlamaz.

Üçüncü olarak, öğeye şablon DOM eklemek için özel öğenin connectedCallback işlevini kullanmanız gerekir. Web bileşeni belirtimine göre, özel öğelerin yapıcı işlevi sırasında alt öğeleri eklememesi gerekir, bu nedenle DOM'yi connectedCallback işlevine eklemeyi ertelemeniz gerekir.

Son olarak, <slot> öğesi gölge DOM'nin dışında çalışmaz. Bu, geliştiricilerin içeriklerini özel öğenize eklemeleri için bir yol sağlamak için farklı bir yöntem kullanmanız gerekeceği anlamına gelir. Genellikle bu, içeriklerini istediğiniz yere eklemek için DOM'yi kendiniz manipüle etmeyi gerektirir.

Ancak, gölge DOM ile özel öğeler içeren hafif DOM arasında bir ayrım olmadığından, öğelerinizin basamaklı stilleri nedeniyle, eklenen DOM'nin stilini belirlememeye de çok dikkat etmeniz gerekir.

 <!-- login-form.html --> <template> <style> login-form .container { max-width: 300px; padding: 50px; border: 1px solid grey; } login-form .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> (function() { const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); } // Without the shadow DOM, we have to manipulate the custom element // after it has been inserted in the DOM. connectedCallback() { const temp = document.importNode(template.content, true); this.appendChild(temp); } }); })(); </script>
 <!-- index.html --> <link rel="stylesheet" href="styleguide.css"> <link rel="import" href="login-form.html"> <login-form></login-form>

Performans açısından, özel öğeler neredeyse kullanılmayan web bileşenleri kadar hızlıdır (yani, paylaşılan stil sayfasını head birbirine bağlamak ve yalnızca yerel DOM öğelerini kullanmak). Bugün kullanabileceğiniz tüm teknikler arasında açık ara en hızlısı bu.

Özel öğe performansının çubuk grafiği.
İki performans testinden elde edilen sonuçlar, özel öğelerin neredeyse web bileşenlerini hiç kullanmamak kadar hızlı olduğunu gösteriyor.

Kenara: Özel bir öğe, tüm amaç ve amaçlar için hala bir web bileşenidir. "Web bileşenleri" terimi, dört ayrı teknolojiyi tanımlamak için kullanılır: özel öğeler, şablon etiketleri, HTML içe aktarmaları ve gölge DOM.

Ne yazık ki, bu terim, dört teknolojinin herhangi bir kombinasyonunu kullanan herhangi bir şeyi tanımlamak için kullanılmıştır. Bu, insanların "web bileşeni" dediğinde ne anlama geldiği konusunda çok fazla kafa karışıklığına neden oldu. Rob Dodson'ın keşfettiği gibi, gölge DOM'lu ve gölgesiz özel öğeler hakkında konuşurken farklı terimler kullanmayı yararlı buldum.

Konuştuğum geliştiricilerin çoğu, "web bileşeni" terimini gölge DOM'yi kullanan özel bir öğeyle ilişkilendirme eğilimindedir. Bu nedenle, bu makalenin amaçları doğrultusunda, bir web bileşeni ile özel bir öğe arasında yapay bir ayrım oluşturdum.

Web Bileşeni Kitaplığı Kullanma

Bugün kullanabileceğiniz başka bir çözüm, Polymer, SkateJS veya X-Tag gibi bir web bileşeni kitaplığıdır. Bu kitaplıklar, bugünün desteğinin boşluklarını doldurmaya yardımcı olur ve ayrıca bir web bileşeni oluşturmak için gerekli kodu basitleştirebilir. Ayrıca genellikle web bileşenlerini yazmayı kolaylaştıran ek özellikler sağlarlar.

Örneğin, Polymer, JavaScript'in yalnızca birkaç satırında basit bir web bileşeni oluşturmanıza olanak tanır. Ek bir avantaj, Polymer'in gölge DOM ve paylaşılan bir stil sayfası kullanmak için bir çözüm sağlamasıdır. Bu, stilleri paylaşan web bileşenleri oluşturabileceğiniz anlamına gelir.

Bunu yapmak için, paylaşılan stillerin tümünü içeren stil modülü dedikleri şeyi oluşturun. Bu, paylaşılan stiller satır içine alınmış bir <style> etiketi veya paylaşılan bir stil sayfasına işaret eden bir <link rel=“import”> etiketi olabilir. Her iki durumda da stilleri web bileşeninize bir <style include> etiketi ile ekleyin, ardından Polymer stilleri ayrıştırır ve bunları web bileşeninize satır içi <style> etiketi olarak ekler.

 <!-- shared-styles.html --> <dom-module> <!-- Link to a shared style sheet --> <!-- <link rel="import" href="styleguide.css"> --> <!-- Inline the shared styles --> <template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } /* Rest of shared CSS */ </style> </template> </dom-module>
 <!-- login-form.html --> <link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../shared-styles/shared-styles.html"> <dom-module> <template> <!-- Include the shared styles --> <style include="shared-styles"></style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> Polymer({ is: 'login-form' }); </script> </dom-module>

Bir kitaplık kullanmanın tek dezavantajı, web bileşenlerinizin oluşturma süresini geciktirebilmesidir. Bu sürpriz olmamalı çünkü kütüphane kodunun indirilmesi ve işlenmesi zaman alıyor. Sayfadaki hiçbir web bileşeni, kitaplığın işlenmesi bitene kadar işlemeye başlayamaz.

Polymer'in durumunda, yerel web bileşenlerine kıyasla sayfa oluşturma süresini yarım saniyeye kadar geciktirebilir. Stilleri gömen bir stil modülü, stilleri birbirine bağlayan bir stil modülünden biraz daha yavaştır ve stilleri doğrudan web bileşenine gömmek, bir stil modülü kullanmak kadar hızlıdır.

Yine, Polimer, özellikle oluşturma süresini yavaşlatmak için hiçbir şey yapmaz. Polimer kitaplığını indirmek ve tüm harika özelliklerini işlemek ve ayrıca tüm şablon ciltlerini oluşturmak zaman alır. Bu sadece bir web bileşeni kitaplığını kullanmak için yapmanız gereken ödünleşimdir.

Polimer web bileşeni performansının çubuk grafiği.

Performans testlerinden elde edilen sonuçlar, Polimer kullanıldığında web bileşenlerinin yerel web bileşenlerine göre yarım saniyeye kadar daha yavaş işleneceğini göstermektedir.

Geleceğin Vaadi

Mevcut çözümlerin hiçbiri sizin için işe yaramazsa, umutsuzluğa kapılmayın. Her şey yolunda giderse, birkaç aydan birkaç yıla kadar, birkaç farklı yaklaşım kullanarak paylaşılan stilleri kullanabileceğiz.

Özel Özellikler

Özel özellikler (veya çağrıldıkları şekliyle CSS değişkenleri), CSS'de değişkenleri ayarlamanın ve kullanmanın bir yoludur. Bu kavram, CSS ön işlemcileri için yeni değildir, ancak yerel bir CSS özelliği olarak, özel özellikler aslında bir ön işlemci değişkeninden daha güçlüdür.

Özel bir özellik bildirmek için, –my-variable: value özel özellik gösterimini kullanın ve property: var(–my-variable) kullanarak değişkene erişin. Özel bir özellik, diğer herhangi bir CSS kuralı gibi basamaklanır, bu nedenle değeri üst öğesinden devralır ve geçersiz kılınabilir. Özel özelliklere ilişkin tek uyarı, bunların bir seçici içinde bildirilmesi gerektiği ve bir önişlemci değişkeninin aksine kendi başlarına bildirilemeyeceğidir.

 <style> /* Declare the custom property */ html { --main-bg-color: red; } /* Use the custom property */ input { background: var(--main-bg-color); } </style>

Özel özellikleri bu kadar güçlü yapan şeylerden biri, gölge DOM'yi delme yetenekleridir. Bu, /deep/ ve ::shadow seçicileriyle aynı fikir değildir çünkü web bileşenine girmeye zorlamazlar. Bunun yerine, web bileşeninin yazarı, uygulanabilmesi için CSS'lerinde özel özelliği kullanmalıdır. Bu, bir web bileşeni yazarının, web bileşeni tüketicilerinin kendi stillerini uygulamak için kullanabileceği özel bir özellik API'si oluşturabileceği anlamına gelir.

 <template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>

Özel özellikler için tarayıcı desteği şaşırtıcı derecede iyidir. Bunun bugün kullanabileceğiniz bir çözüm olmamasının tek nedeni, Custom Elements sürüm 1 olmadan çalışan bir polyfill olmamasıdır. Webcomponentjs polyfill'in arkasındaki ekip şu anda onu eklemek için çalışıyor, ancak henüz piyasaya sürülmedi ve yerleşik durumda, yani varlıklarınızı üretim için hash ederseniz, onu kullanamazsınız. Anladığım kadarıyla, önümüzdeki yılın başlarında piyasaya sürülecek.

Buna rağmen, özel özellikler, web bileşenleri arasında stil paylaşımı için iyi bir yöntem değildir. Yalnızca tek bir özellik değeri bildirmek için kullanılabildikleri için, web bileşeninin yine de stil kılavuzunun tüm stillerini, değerleri değişkenlerle değiştirilmiş olsa da gömmesi gerekir.

Özel özellikler, paylaşılan stillerden ziyade tema seçeneklerine daha uygundur. Bu nedenle, özel özellikler sorunumuza uygun bir çözüm değil.

/* Özel özelliği kullan */ input { background: var(–main-bg-color); } </stil>

Özel özellikleri bu kadar güçlü yapan şeylerden biri, gölge DOM'yi delme yetenekleridir. Bu, /deep/ ve ::shadow seçicileriyle aynı fikir değildir çünkü web bileşenine girmeye zorlamazlar. Bunun yerine, web bileşeninin yazarı, uygulanabilmesi için CSS'lerinde özel özelliği kullanmalıdır. Bu, bir web bileşeni yazarının, web bileşeni tüketicilerinin kendi stillerini uygulamak için kullanabileceği özel bir özellik API'si oluşturabileceği anlamına gelir.

 <template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>

Özel özellikler için tarayıcı desteği şaşırtıcı derecede iyidir. Bunun bugün kullanabileceğiniz bir çözüm olmamasının tek nedeni, Custom Elements sürüm 1 olmadan çalışan bir polyfill olmamasıdır. Webcomponentjs polyfill'in arkasındaki ekip şu anda onu eklemek için çalışıyor, ancak henüz piyasaya sürülmedi ve yerleşik durumda, yani varlıklarınızı üretim için hash ederseniz, onu kullanamazsınız. Anladığım kadarıyla, önümüzdeki yılın başlarında piyasaya sürülecek.

Buna rağmen, özel özellikler, web bileşenleri arasında stil paylaşımı için iyi bir yöntem değildir. Yalnızca tek bir özellik değeri bildirmek için kullanılabildikleri için, web bileşeninin yine de stil kılavuzunun tüm stillerini, değerleri değişkenlerle değiştirilmiş olsa da gömmesi gerekir.

Özel özellikler, paylaşılan stillerden ziyade tema seçeneklerine daha uygundur. Bu nedenle, özel özellikler sorunumuza uygun bir çözüm değil.

@apply Kuralları

Özel özelliklere ek olarak, CSS @apply kuralları da alıyor. Uygulama kuralları, esasen CSS dünyası için karışımlardır. Özel özelliklere benzer şekilde bildirilirler ancak yalnızca özellik değerleri yerine özellik gruplarını bildirmek için kullanılabilirler. Özel özellikler gibi, değerleri devralınabilir ve geçersiz kılınabilir ve çalışabilmeleri için bir seçici içinde bildirilmeleri gerekir.

 <style> /* Declare rule */ html { --typography: { font: 16px Arial, sans-serif; color: #333333; } } /* Use rule */ input { @apply --typography; } </style>

@apply kuralları için tarayıcı desteği temelde mevcut değildir. Chrome şu anda onu bir özellik bayrağının arkasında destekliyor (ki bulamadım), ancak bu kadar. Özel özellikler için çoklu dolgu olmadığı gibi aynı nedenle çalışan bir çoklu dolgu da yoktur. webcomponentjs polyfill ekibi ayrıca özel özelliklerle birlikte @apply kuralları eklemek için çalışıyor, bu nedenle her ikisi de yeni sürüm yayınlandığında kullanılabilir olacak.

Özel özelliklerin aksine @apply kuralları, stilleri paylaşmak için çok daha iyi bir çözümdür. Bir grup özellik bildirimi ayarlayabildikleri için, bunları tüm yerel öğeler için varsayılan stili ayarlamak için kullanabilir ve ardından bunları web bileşeni içinde kullanabilirsiniz. Bunu yapmak için, her yerel öğe için bir @apply kuralı oluşturmanız gerekir.

Bununla birlikte, stilleri tüketmek için bunları her yerel öğeye manuel olarak uygulamanız gerekir, bu da stil bildirimini her web bileşeninde yineler. Bu, tüm stilleri gömmekten daha iyi olsa da, stillerin düzgün çalışması için eklemeyi hatırlamanız gereken her web bileşeninin en üstünde standart hale geldiğinden çok uygun değildir.

 /* styleguide.css */ html { --typography: { color: #333333; font: 16px Arial, sans-serif; } --paragraph: { margin: 0; } --label { display: block; margin-bottom: 5px; } --input-text { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } --input-submit { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } /* And so on for every native element */ }
 <!-- login-form.html --> <template> <style> :host { @apply --typography; } p { @apply --paragraph; } label { @apply --label; } input-text { @apply --input-text; } .input-submit { @apply --input-submit; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template>

Kapsamlı ortak bilgi ihtiyacı nedeniyle, @apply kurallarının web bileşenleri arasında stil paylaşımı için iyi bir çözüm olacağına inanmıyorum. Yine de tema için harika bir çözüm.

Gölge DOM'da

Web bileşeni spesifikasyonuna göre, tarayıcılar gölge DOM'deki herhangi bir <link rel=“stylesheet”> etiketini yok sayar ve onlara tıpkı bir belge parçasının içindeymiş gibi davranır. Bu, web bileşenlerimizdeki herhangi bir paylaşılan stilde bağlantı kurabilmemizi engelledi, bu talihsiz bir durumdu - yani birkaç ay öncesine kadar, Web Bileşenleri Çalışma Grubu <link rel=“stylesheet”> etiketlerinin çalışmasını önerene kadar gölge DOM. Sadece bir haftalık tartışmadan sonra, hepsi yapılması gerektiği konusunda anlaştılar ve birkaç gün sonra bunu HTML spesifikasyonuna eklediler.

 <template> <link rel="stylesheet" href="styleguide.css"> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>

Bu, çalışma grubunun bir şartname üzerinde anlaşmaya varması için biraz fazla hızlı geliyorsa, bunun nedeni yeni bir teklif olmamasıdır. link etiketlerinin gölge DOM'de çalışmasını sağlamak aslında en az üç yıl önce önerildi, ancak performans için bir sorun olmadığından emin olana kadar birikmişti.

Teklifin kabul edilmesi yeterince heyecan verici değilse, Chrome 55 (şu anda Chrome Canary), link etiketlerinin gölge DOM'de çalışmasını sağlayan ilk işlevi ekledi. Hatta bu işlevsellik, Chrome'un mevcut sürümüne dahil edilmiş gibi görünüyor. Safari bile bu özelliği Safari 18'de uygulamıştır.

Paylaşılan stillerde bağlantı kurabilmek, web bileşenleri arasında stilleri paylaşmak için açık ara en uygun yöntemdir. Tek yapmanız gereken link etiketini oluşturmaktır ve tüm yerel öğeler, herhangi bir ek çalışma gerektirmeden buna göre biçimlendirilir.

Elbette, tarayıcı üreticilerinin özelliği uygulama şekli, bu çözümün uygulanabilir olup olmadığını belirleyecektir. Bunun düzgün çalışması için link etiketlerinin tekilleştirilmesi gerekir, böylece aynı CSS dosyasını isteyen birden çok web bileşeni yalnızca bir HTTP isteğine neden olur. Ayrıca, web bileşeninin her örneğinin paylaşılan stilleri yeniden hesaplaması gerekmeyecek, bunun yerine hesaplanan stilleri yeniden kullanması için CSS'nin yalnızca bir kez ayrıştırılması gerekir.

Chrome bunların ikisini de zaten yapıyor. Bu nedenle, diğer tüm tarayıcı üreticileri bunu aynı şekilde uygularsa, gölge DOM'da çalışan link etiketleri, stillerin web bileşenleri arasında nasıl paylaşılacağı sorununu kesinlikle çözecektir.

Yapılandırılabilir Stil Sayfaları

Henüz elimizde olmadığı için inanmakta zorlanabilirsiniz, ancak gölge DOM'de çalışan bir link etiketi uzun vadeli bir çözüm değildir. Bunun yerine, bizi gerçek çözüme ulaştırmak için sadece kısa vadeli bir çözüm: yapılandırılabilir stil sayfaları.

Yapılandırılabilir stil sayfaları, bir yapıcı işlevi aracılığıyla JavaScript'te StyleSheet nesnelerinin oluşturulmasına izin veren bir tekliftir. Oluşturulan stil sayfası daha sonra bir API aracılığıyla gölge DOM'ye eklenebilir, bu da gölge DOM'nin bir dizi paylaşılan stil kullanmasına izin verir.

Ne yazık ki, tekliften toplayabildiğim tek şey bu. Web Bileşenleri Çalışma Grubuna sorarak oluşturulabilir stil sayfalarının ne olduğu hakkında daha fazla bilgi bulmaya çalıştım, ancak beni tekrar W3C'nin CSS Çalışma Grubu'nun posta listesine yönlendirdiler, burada tekrar sordum ama kimse yanıt vermedi. Teklifin nasıl ilerlediğini bile anlayamadım çünkü iki yılı aşkın süredir güncellenmedi.

Öyle olsa bile, Web Bileşenleri Çalışma Grubu bunu web bileşenleri arasında stil paylaşımı için bir çözüm olarak kullanır. Umarım ya teklif güncellenir ya da Web Bileşenleri Çalışma Grubu teklif ve kabulü hakkında daha fazla bilgi yayınlar. O zamana kadar, “uzun vadeli” çözüm, yakın gelecekte olmayacak gibi görünüyor.

Dersler öğrenildi

Aylarca süren araştırma ve testlerden sonra, gelecek için oldukça umutluyum. Web bileşenleri arasında stil paylaşımı için yıllarca bir çözüm bulamamanın ardından nihayet yanıtların olduğunu bilmek rahatlatıcı. Bu cevaplar birkaç yıl daha belirlenmemiş olabilir, ama en azından oradalar.

Bugün web bileşenlerine stil vermek için paylaşılan bir stil kılavuzu kullanmak istiyorsanız, ya gölge DOM'yi kullanamaz ve bunun yerine özel öğeler oluşturamazsınız ya da stillerin paylaşılması için çoklu dolgu desteği sağlayan bir web bileşeni kitaplığı kullanabilirsiniz. Her iki çözümün de artıları ve eksileri vardır, bu nedenle projeniz için en uygun olanı kullanın.

Web bileşenlerini incelemeden önce bir süre beklemeye karar verirseniz, birkaç yıl içinde stilleri aralarında paylaşmak için harika çözümlerimiz olacaktır. Bu nedenle, nasıl ilerlediğini tekrar kontrol etmeye devam edin.

Akılda Tutulması Gerekenler

Bugün özel öğeler veya web bileşenleri kullanmaya karar verirseniz birkaç şeyi aklınızda bulundurun.

En önemlisi, web bileşeni spesifikasyonu hala aktif olarak geliştirilmektedir, bu da her şeyin değişebileceği ve değişeceği anlamına gelir. Web bileşenleri hala en son teknolojidir, bu yüzden onu geliştirirken ayaklarınızın üzerinde durmaya hazır olun.

Gölge DOM'yi kullanmaya karar verirseniz, bunun çok dolgulu tarayıcılarda oldukça yavaş ve performanssız olduğunu bilin. Bu nedenle Polymer'in geliştiricileri gölgeli DOM uygulamalarını oluşturdular ve bunu varsayılanları yaptılar.

Chrome, Opera ve yakın zamanda Safari, gölge DOM sürüm 0'ı destekleyen tek tarayıcılardır. Firefox, sürüm 29'dan bu yana bir denemenin arkasında desteklemesine rağmen hala geliştirme aşamasındadır. Microsoft hala Edge için düşünüyor ve bir yol haritasında yüksek önceliğe sahiptir.

Ancak, gölge DOM sürüm 0 eski belirtimdir. Shadow DOM sürüm 1 yenidir ve yalnızca Chrome, Safari ve Opera onu tam olarak destekler. Özel öğeler sürüm 0'ın aynı yükseltmeden geçtiğini ve yalnızca Chrome'un özel öğeler sürüm 1'i tamamen desteklediğini ve Safari teknik önizlemesinin sürüm 17'den itibaren desteklediğini belirtmeye gerek yok. Özel öğeler sürüm 1, web bileşenlerinin yazılma biçiminde bazı önemli değişikliklere sahiptir, bu yüzden bunun ne anlama geldiğini tam olarak anladığınızdan emin olun.

Son olarak, webcomponentjs polyfill yalnızca gölge DOM'nin ve özel öğelerin sürüm 0 uygulamasını destekler. Polyfill'in bir sürüm 1 dalı, sürüm 1'i destekleyecektir, ancak henüz piyasaya sürülmemiştir.