Geliştirici Araçları'nda JS içinde CSS desteği

Ali Rıza
Alex Rudenko

Bu makalede, Chrome 85'ten beri kullanıma sunulan Geliştirici Araçları'nda CSS-in-JS desteği, genel olarak CSS-in-JS ile neyi kastettiğimiz ve bu desteğin uzun süredir Geliştirici Araçları tarafından desteklenen normal CSS'den farkı açıklanmaktadır.

JS'de CSS nedir?

CSS-in-JS'nin tanımı oldukça belirsizdir. Genel anlamda, JavaScript kullanarak CSS kodunu yönetmeye yönelik bir yaklaşımdır. Örneğin, CSS içeriğinin JavaScript kullanılarak tanımlandığı ve nihai CSS çıkışının uygulama tarafından anında oluşturulduğu anlamına gelebilir.

Geliştirici Araçları bağlamında CSS-in-JS, CSS içeriğinin CSSOM API'leri kullanılarak sayfaya yerleştirildiği anlamına gelir. Normal CSS, <style> veya <link> öğeleri kullanılarak yerleştirilir ve statik bir kaynağa (ör. DOM düğümü veya ağ kaynağı) sahiptir. Buna karşılık, CSS-in-JS genellikle statik bir kaynağa sahip değildir. Buradaki özel bir durum, bir <style> öğesinin içeriğinin CSSOM API kullanılarak güncellenebilmesidir. Bu durum, kaynağın gerçek CSS stil sayfasıyla senkronize olmamasına neden olur.

JS'de CSS kitaplığı kullanıyorsanız (ör. styled-component, Emotion, JSS) kitaplık, geliştirme moduna ve tarayıcıya bağlı olarak arka planda CSSOM API'lerini kullanarak stilleri ekleyebilir.

CSS-in-JS kitaplıklarının yaptığına benzer bir şekilde CSSOM API'yi kullanarak stil sayfası eklemeyle ilgili bazı örneklere göz atalım.

// Insert new rule to an existing CSS stylesheet
const element = document.querySelector('style');
const stylesheet = element.sheet;
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');

Tamamen yeni bir stil sayfası da oluşturabilirsiniz:

// Create a completely new stylesheet
const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');

// Apply constructed stylesheet to the document
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

Geliştirici Araçları'nda CSS desteği

Geliştirici Araçları'nda, CSS ile çalışırken en yaygın olarak kullanılan özellik Stiller bölmesidir. Stiller bölmesinde, belirli bir öğe için hangi kuralların geçerli olduğunu görüntüleyebilir, kuralları düzenleyebilir ve sayfadaki değişiklikleri gerçek zamanlı olarak görebilirsiniz.

Geçen yıldan önce, CSSOM API'leri kullanılarak değiştirilen CSS kuralları için sunulan destek oldukça sınırlıydı: Uygulanan kuralları yalnızca görebiliyor, ancak düzenleyemiyordunuz. Geçen yılki ana hedefimiz, JS içinde CSS kurallarının Stiller bölmesi kullanılarak düzenlenmesini sağlamaktı. Bazen, Web API'leri kullanılarak oluşturulduklarını belirtmek için CSS-in-JS stillerini "structed" olarak da adlandırıyoruz.

Geliştirici Araçları'ndaki Stil düzenleme çalışmalarının ayrıntılarını inceleyelim.

Geliştirici Araçları'nda stil düzenleme mekanizması

Geliştirici Araçları&#39;nda stil düzenleme mekanizması

Geliştirici Araçları'nda bir öğe seçtiğinizde Stiller bölmesi gösterilir. Stiller bölmesi, öğeye uygulanan CSS kurallarını almak için CSS.getMatchedStylesForNode adlı bir CDP komutu yayınlar. Chrome Geliştirici Araçları Protokolü anlamına gelen CDP, Geliştirici Araçları ön ucunun incelenen sayfa hakkında ek bilgi almasını sağlayan bir API'dir.

CSS.getMatchedStylesForNode çağrıldığında, dokümandaki tüm stil sayfalarını tanımlar ve tarayıcının CSS ayrıştırıcısını kullanarak bunları ayrıştırır. Ardından her CSS kuralını stil sayfası kaynağındaki bir konumla ilişkilendiren bir dizin oluşturur.

CSS'nin neden tekrar ayrıştırılması gerektiğini sorabilirsiniz. Buradaki sorun, performansla ilgili nedenlerle tarayıcının kendisinin CSS kurallarının kaynak konumlarıyla ilgili olmaması ve bu nedenle bunları depolamamasıdır. Ancak Geliştirici Araçları'nın CSS düzenlemesini desteklemek için kaynak konumlarına ihtiyacı vardır. Normal Chrome kullanıcılarının performans cezası ödemelerini istemiyoruz ancak Geliştirici Araçları kullanıcılarının kaynak konumlara erişebilmesini istiyoruz. Bu yeniden ayrıştırma yaklaşımı, her iki kullanım alanını minimum dezavantajla ele alır.

Daha sonra, CSS.getMatchedStylesForNode uygulaması, tarayıcının stil motorundan belirtilen öğeyle eşleşen CSS kurallarını sağlamasını ister. Bu yöntem son olarak stil motoru tarafından döndürülen kuralları kaynak koduyla ilişkilendirir ve CSS kuralları hakkında yapılandırılmış bir yanıt sağlar. Böylece Geliştirici Araçları, kuralın hangi bölümünün seçici veya mülk olduğunu bilir. Geliştirici Araçları'nın, seçiciyi ve özellikleri bağımsız olarak düzenlemesine olanak tanır.

Şimdi düzenlemeye bakalım. CSS.getMatchedStylesForNode işlevinin her kural için kaynak konumları döndürdüğünü hatırlıyor musunuz? Bu, düzenleme için çok önemli. Bir kuralı değiştirdiğinizde, Geliştirici Araçları sayfayı gerçekten güncelleyen başka bir CDP komutu yayınlar. Komut, güncellenen kural parçasının orijinal konumunu ve parçanın güncellenmesi gereken yeni metni içerir.

Geliştirici Araçları, arka uçta düzenleme çağrısını işlerken hedef stil sayfasını günceller. Ayrıca, koruduğu stil sayfası kaynağının kopyasını günceller ve güncellenen kural için kaynak konumlarını günceller. Geliştirici Araçları ön ucu, düzenleme çağrısına yanıt olarak yeni güncellenen metin parçasının güncellenen konumlarını geri alır.

Bu durum, Geliştirici Araçları'nda CSS-in-JS düzenlemenin neden hemen işe yaramadığını açıklamaktadır: CSS-in-JS'nin herhangi bir yerde depolanan gerçek bir kaynağı yoktur ve CSS kuralları, CSSOM veri yapılarında tarayıcının belleğinde mevcuttur.

CSS-in-JS için nasıl destek ekledik?

Dolayısıyla, CSS'in-JS'de kuralların düzenlenmesini desteklemek için en iyi çözümün, yukarıda açıklanan mevcut mekanizmayı kullanarak düzenlenebilecek oluşturulmuş stil sayfaları için bir kaynak oluşturmak olduğuna karar verdik.

İlk adım kaynak metni oluşturmaktır. Tarayıcının stil motoru, CSS kurallarını CSSStyleSheet sınıfında depolar. Bu sınıf, daha önce açıklandığı gibi JavaScript'ten örneklerini oluşturabileceğiniz sınıftır. Kaynak metni oluşturmak için gereken kod aşağıdaki gibidir:

String InspectorStyleSheet::CollectStyleSheetRules() {
  StringBuilder builder;
  for (unsigned i = 0; i < page_style_sheet_->length(); i++) {
    builder.Append(page_style_sheet_->item(i)->cssText());
    builder.Append('\n');
  }
  return builder.ToString();
}

CSSStyleSheet örneğinde bulunan kurallar üzerinde yinelenir ve bundan tek bir dize oluşturur. Bu yöntem, InspectorStyleSheet sınıfının bir örneği oluşturulduğunda çağrılır. InspectorStyleSheet sınıfı bir CSSStyleSheet örneğini sarmalar ve DevTools'un gerektirdiği ek meta verileri ayıklar:

void InspectorStyleSheet::UpdateText() {
  String text;
  bool success = InspectorStyleSheetText(&text);
  if (!success)
    success = InlineStyleSheetText(&text);
  if (!success)
    success = ResourceStyleSheetText(&text);
  if (!success)
    success = CSSOMStyleSheetText(&text);
  if (success)
    InnerSetText(text, false);
}

Bu snippet'te CSSOMStyleSheetText öğesinin CollectStyleSheetRules kodunu dahili olarak çağırdığını görüyoruz. Stil sayfası satır içi değilse veya bir kaynak stil sayfası değilse CSSOMStyleSheetText çağrılır. Temel olarak bu iki snippet, new CSSStyleSheet() oluşturucusu kullanılarak oluşturulan stil sayfalarının temel bir şekilde düzenlenmesine zaten olanak tanır.

Özel bir durum, CSSOM API kullanılarak dönüştürülen <style> etiketiyle ilişkili stil sayfalarıdır. Bu durumda, stil sayfası kaynak metni ve kaynakta var olmayan ek kuralları içerir. Bu durumu düzeltmek için bu ek kuralları kaynak metinde birleştirmek için bir yöntem sunuyoruz. CSS kuralları orijinal kaynak metnin ortasına eklenebileceği için burada sıra önemlidir. Örneğin, orijinal <style> öğesinin aşağıdaki metni içerdiğini düşünün:

/* comment */
.rule1 {}
.rule3 {}

Ardından sayfa, JS API'yi kullanarak şu kurallar sıralamasını oluşturan bazı yeni kurallar ekler: .rule0, .rule1, .rule2, .rule3, .rule4. Birleştirme işleminden sonra elde edilen kaynak metin aşağıdaki gibi olmalıdır:

.rule0 {}
/* comment */
.rule1 {}
.rule2 {}
.rule3 {}
.rule4 {}

Kuralların kaynak metin konumlarının kesin olması gerektiğinden, orijinal yorumların ve girintinin korunması, düzenleme işlemi açısından önemlidir.

CSS-in-JS stil sayfaları için özel olan bir başka özellik de bu sayfaların sayfa tarafından herhangi bir zamanda değiştirilebilmesidir. Gerçek CSSOM kuralları metin sürümüyle senkronize olmazsa düzenleme çalışmaz. Bu amaçla, bir stil sayfası değiştirilirken tarayıcının Geliştirici Araçları'nın arka uç kısmına bildirimde bulunmasını sağlayan prob adlı bir aracı kullanıma sunduk. Dönüştürülen stil sayfaları, CSS.getEşleşenStylesForNode için bir sonraki çağrı sırasında senkronize edilir.

Tüm bu özellikler uygulandığında, CSS-in-JS düzenlemesi zaten çalışıyor ancak bir stil sayfasının oluşturulup oluşturulmadığını belirtmek için kullanıcı arayüzünü iyileştirmek istedik. CDP'nin CSS.CSSStyleSheetHeader öğesine isConstructed adlı yeni bir özellik ekledik. Ön ucun CSS kuralının kaynağını düzgün bir şekilde görüntülemek için kullandığı bu özelliği kullanabilirsiniz:

Oluşturulabilir stil sayfası

Sonuçlar

Hikayemizi burada özetlemek gerekirse Geliştirici Araçları'nın desteklemediği CSS-in-JS ile ilgili kullanım alanlarını inceledik ve bu kullanım alanlarını desteklemek üzere ilgili çözümü inceledik. Bu uygulamanın ilginç tarafı, CSSOM CSS kurallarını normal bir kaynak metne sahip hale getirerek mevcut işlevlerden yararlanabilmemiz ve böylece Geliştirici Araçları'nda stil düzenlemeyi tamamen yeniden tasarlama ihtiyacını ortadan kaldırabilmemizdir.

Daha fazla bilgi için tasarım teklifimize veya ilgili tüm yamalara referans veren Chromium izleme hatasına göz atın.

Önizleme kanallarını indirme

Varsayılan geliştirme tarayıcınız olarak Chrome Canary, Yeni geliştirilenler veya Beta sürümünü kullanabilirsiniz. Bu önizleme kanalları ile Geliştirici Araçları'nın en yeni özelliklerine erişebilir, son teknoloji ürünü web platformu API'lerini test edebilir ve sitenizdeki sorunları kullanıcılarınızdan önce tespit edebilirsiniz.

Chrome Geliştirici Araçları ekibiyle iletişime geçme

Yayındaki yeni özellikler ve değişiklikler ya da Geliştirici Araçları ile ilgili diğer konular hakkında konuşmak için aşağıdaki seçenekleri kullanın.

  • crbug.com adresinden bize öneri veya geri bildirim gönderin.
  • Geliştirici Araçları'nda Diğer seçenekler > Yardım > Geliştirici Araçları sorunu bildir'i kullanarak Geliştirici Araçları sorunlarını bildirin.Daha fazla
  • @ChromeDevTools adresine tweet gönderin.
  • Geliştirici Araçları YouTube videoları bölümündeki yenilikler veya Geliştirici Araçları İpuçları YouTube videoları bölümlerimize yorum yapın.