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

Alex Rudenko
Alex Rudenko

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

JS'de CSS nedir?

JS'de CSS'nin tanımı oldukça belirsizdir. Geniş anlamda CSS kodunu yönetmek için JavaScript'i kullanan bir yaklaşımdır. Örneğin, CSS içeriğinin JavaScript kullanılarak tanımlandığı ve son 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, JS'de CSS çoğu zaman statik bir kaynağa sahip değildir. Buradaki özel bir durum, <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.

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

Şimdi de CSS-in-JS kitaplıklarının yaptıklarına benzer şekilde CSSOM API'yi kullanarak stil sayfasını nasıl yerleştirebileceğinize dair bazı örneklere bakalı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 öğeye hangi kuralların uygulandığını 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 destek oldukça sınırlıydı: Sadece uygulanan kuralları görebiliyordunuz ancak düzenleyemiyordunuz. Geçen yılki temel hedefimiz, Stiller bölmesini kullanarak CSS-in-JS kurallarının düzenlenmesine olanak tanımaktı. Bazen, Web API'leri kullanılarak oluşturulduklarını belirtmek için CSS-in-JS stillerini "structured" olarak da adlandırırız.

Geliştirici Araçları'nda stil düzenleme işleminin ayrıntılarına göz atalım.

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 adında bir CDP komutu yayınlar. CDP, Chrome Geliştirici Araçları Protokolü anlamına gelir ve Geliştirici Araçları ön ucunun denetlenen 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 bunları tarayıcının CSS ayrıştırıcısını kullanarak 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, performans nedeniyle tarayıcının kendisinin CSS kurallarının kaynak konumları ile ilgilenmemesi ve dolayısıyla 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şim sahibi olmalarını istiyoruz. Bu yeniden ayrıştırma yaklaşımı, her iki kullanım alanını da minimum dezavantajla ele alır.

Daha sonra CSS.getMatchedStylesForNode uygulaması, tarayıcının stil motorundan belirtilen öğeyle eşleşen CSS kuralları sağlamasını ister. Son olarak yöntem, 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 özellikler 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 önemlidir. Bir kuralı değiştirdiğinizde Geliştirici Araçları, sayfayı güncelleyen başka bir CDP komutu yayınlar. Bu 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ı yürütürken hedef stil sayfasını günceller. Ayrıca, koruduğu stil sayfası kaynağının kopyasını da günceller ve güncellenmiş kural için kaynak konumlarını günceller. Düzenleme çağrısına yanıt olarak, Geliştirici Araçları ön ucu, yeni güncellenen metin parçasının güncellenmiş konumlarını geri alır.

Bu, Geliştirici Araçları'nda CSS-in-JS'yi düzenlemenin neden anında gerçekleştirilemediğini açıklar: CSS-in-JS'nin hiçbir yerde gerçek bir kaynağı yoktur ve CSS kuralları, CSSOM veri yapılarında tarayıcının belleğinde yer alır.

CSS-in-JS için desteği nasıl ekledik?

Dolayısıyla, JS'de CSS kurallarının düzenlenmesini desteklemek için, en iyi çözümün, oluşturulmuş stil sayfaları için yukarıda açıklanan mevcut mekanizma kullanılarak düzenlenebilecek 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 örnekleri 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();
}

Bir CSSStyleSheet örneğinde bulunan kuralları yineler 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 Geliştirici Araçları'nın ihtiyaç duyduğu 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, dahili olarak CollectStyleSheetRules çağrısı yapan CSSOMStyleSheetText adı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 zaten new CSSStyleSheet() oluşturucusu kullanılarak oluşturulan stil sayfalarının temel düzenlenmesine olanak tanır.

Özel bir durum, CSSOM API kullanılarak değiştirilen bir <style> etiketiyle ilişkili stil sayfalarıdır. Bu durumda stil sayfası, kaynak metni ve kaynakta bulunmayan ek kuralları içerir. Bu durumu ele almak için bu ek kuralları kaynak metinde birleştiren bir yöntem sunduk. CSS kuralları orijinal kaynak metnin ortasına eklenebildiğinden burada sıra önemlidir. Örneğin, orijinal <style> öğesinin şu metni içerdiğini varsayalım:

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

Ardından sayfa, JS API'yi kullanarak şu kural sırasını oluşturan bazı yeni kurallar ekledi: .rule0, .rule1, .rule2, .rule3, .rule4. Birleştirme işleminden sonra ortaya çıkan 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 için önemlidir.

JS'de CSS 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 edilmezse 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ını bilgilendirmesini sağlayan probe adlı bir özelliği kullanıma sunduk. Üzerinde değişiklik yapılan stil sayfaları, daha sonra CSS.getMatchStylesForNode için yapılan bir sonraki çağrı sırasında senkronize edilir.

Tüm bu parçalar yerine, CSS-in-JS düzenlemesi zaten çalışıyor. Ancak, bir stil sayfasının oluşturulup oluşturulmadığını göstermek için kullanıcı arayüzünü geliştirmek istedik. CDP'nin CSS.CSSStyleSheetHeader'ına, ön ucun CSS kuralının kaynağını düzgün bir şekilde görüntülemek için kullandığı isConstructed adlı yeni bir özellik ekledik:

Oluşturulabilir stil sayfası

Sonuçlar

Hikayemizi özetlemek gerekirse CSS-in-JS ile ilgili olarak Geliştirici Araçları'nın desteklemediği ilgili kullanım alanlarına baktık ve bu kullanım alanlarını desteklemek üzere çözümün üzerinden geçtik. Bu uygulamanın ilginç yanı, CSSOM CSS kurallarının normal kaynak metni olmasını sağlayarak mevcut işlevlerden yararlanmamız oldu. Böylece, Geliştirici Araçları'nda stil düzenlemenin tamamen yeniden tasarlanması gerekmiyor.

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, Dev veya Beta'yı kullanabilirsiniz. Bu önizleme kanalları en yeni Geliştirici Araçları özelliklerine erişmenizi, son teknoloji ürünü web platformu API'lerini test etmenizi ve kullanıcılarınızdan önce sitenizdeki sorunları bulmanızı sağlar.

Chrome Geliştirici Araçları ekibiyle iletişim kurma

Yayındaki yeni özellikleri ve değişiklikleri ya da Geliştirici Araçları ile ilgili diğer her şeyi tartışmak için aşağıdaki seçenekleri kullanın.

  • Öneri veya geri bildirimlerinizi crbug.com adresinden bize iletebilirsiniz.
  • Geliştirici Araçları'ndaki Diğer seçenekler   Diğer > Yardım > Geliştirici Araçları ile ilgili sorun bildir bölümüne giderek Geliştirici Araçları sorunlarını bildirin.
  • @ChromeDevTools adresinden tweet atabilirsiniz.
  • Geliştirici Araçları YouTube videoları veya Geliştirici Araçları ipuçları YouTube videolarına yorum yazın.