Kapsayıcı sorgusu polyfill içinde

Gerald Monaco
Gerald Monaco

Kapsayıcı sorguları, alt öğelerin stilini belirlemek için bir üst öğenin özelliklerini (örneğin, genişliği veya yüksekliği) hedefleyen stil mantığı yazmanıza olanak tanıyan yeni bir CSS özelliğidir. Kısa süre önce, tarayıcılarda destekle ilgili olarak çoklu dolguda yapılan büyük bir güncelleme yayınlandı.

Bu gönderide, çoklu dolgunun çalışma şekline, üstesinden geldiği zorluklara ve ziyaretçilerinize mükemmel bir kullanıcı deneyimi sunmak için çoklu dolgunun kullanıldığı en iyi uygulamalara göz atabileceksiniz.

Gelişmiş seçenekler

Transpilasyon

Bir tarayıcı içindeki CSS ayrıştırıcı, yepyeni @container kuralı gibi bilinmeyen bir kuralla karşılaştığında, bu kuralı hiç varmış gibi siler. Bu nedenle, çoklu dolgunun yapması gereken ilk ve en önemli şey, bir @container sorgusunu silinmeyecek bir şeye dönüştürmektir.

Transpilasyonda ilk adım, üst düzey @container kuralını bir @media sorgusuna dönüştürmektir. Bu sayede genelde içeriğin birlikte gruplanmış olarak kalmasını sağlarsınız. Örneğin, CSSOM API'lerini kullanırken ve CSS kaynağını görüntülerken.

Önce
@container (width > 300px) {
  /* content */
}
Sonra
@media all {
  /* content */
}

Kapsayıcı sorgularından önce, CSS'de yazarların kural gruplarını rastgele etkinleştirebileceği veya devre dışı bırakabileceği bir yöntem bulunmuyordu. Bu davranışı çoklu doldurmak için bir kapsayıcı sorgusu içindeki kuralların da dönüştürülmesi gerekir. Her @container için kendine özgü bir kimlik verilir (örneğin, 123). Bu kimlik, her bir seçiciyi dönüştürmek için kullanılır ve yalnızca öğede bu kimliği içeren bir cq-XYZ özelliği olduğunda uygulanır. Bu özellik, çalışma zamanında çoklu dolgu tarafından ayarlanır.

Önce
@container (width > 300px) {
  .card {
    /* ... */
  }
}
Sonra
@media all {
  .card:where([cq-XYZ~="123"]) {
    /* ... */
  }
}

:where(...) sözde sınıfının kullanıldığına dikkat edin. Normalde ek bir özellik seçicinin eklenmesi, seçicinin spesifikliğini artırır. Sanal sınıf ile ekstra koşul, orijinal özgünlük korunurken uygulanabilir. Bunun neden çok önemli olduğunu anlamak için aşağıdaki örneği inceleyin:

@container (width > 300px) {
  .card {
    color: blue;
  }
}

.card {
  color: red;
}

Bu CSS göz önünde bulundurulduğunda, .card sınıfına sahip bir öğe her zaman color: red içermelidir. Çünkü sonraki kural, önceki kuralı her zaman aynı seçici ve kesinlikle geçersiz kılar. Dolayısıyla, ilk kuralın aktarılması ve :where(...) olmadan ek bir özellik seçicinin eklenmesi, kesinliği artırır ve color: blue öğesinin hatalı bir şekilde uygulanmasına neden olur.

Ancak, :where(...) sözde sınıfı oldukça yenidir. Çoklu dolgu, bu özelliği desteklemeyen tarayıcılar için güvenli ve kolay bir çözüm sağlar: @container kurallarınıza manuel olarak model bir :not(.container-query-polyfill) seçici ekleyerek kurallarınızın kesinliğini kasıtlı olarak artırabilirsiniz:

Önce
@container (width > 300px) {
  .card {
    color: blue;
  }
}

.card {
  color: red;
}
Sonra
@container (width > 300px) {
  .card:not(.container-query-polyfill) {
    color: blue;
  }
}

.card {
  color: red;
}

Bunun çeşitli avantajları vardır:

  • Kaynak CSS'deki seçici değiştiği için belirginlikteki fark açıkça görülebiliyor. Bu aynı zamanda belge görevi görür. Böylece, geçici çözümü veya çoklu dolguyu desteklemeye artık ihtiyaç duymadığınızda nelerin etkileneceğini bilirsiniz.
  • Çoklu dolgu onu değiştirmediği için kuralların kesinliği her zaman aynıdır.

Aktarma sırasında çoklu dolgu, bu temsili aynı belirginliğe sahip özellik seçiciyle değiştirir. Sürprizlerle karşılaşmamak için çoklu dolguda her iki seçici de kullanılır: Öğenin çoklu dolgu özelliğini alıp almayacağını belirlemek için orijinal kaynak seçici, stil olarak da aktarılan seçici kullanılır.

Sözde öğeler

Kendinize şu soruyu sorabilirsiniz: Polyfill, bir öğede benzersiz kapsayıcı kimliğini (123) içerecek şekilde bazı cq-XYZ özellikleri ayarlarsa, üzerinde özellikler ayarlanmamış sözde öğeler nasıl desteklenebilir?

Sözde öğeler, her zaman DOM'deki kaynak öğe adı verilen gerçek bir öğeye bağlıdır. Aktarma sırasında, koşullu seçici şu gerçek öğeye uygulanır:

Önce
@container (width > 300px) {
  #foo::before {
    /* ... */
  }
}
Sonra
@media all {
  #foo:where([cq-XYZ~="123"])::before {
    /* ... */
  }
}

Koşullu seçici, #foo::before:where([cq-XYZ~="123"]) biçimine dönüştürülmek (bu durum geçersiz olur) yerine #foo kaynak öğesinin sonuna taşınır.

Ancak tüm yapmanız gereken bu değil. Bir kapsayıcının, içinde olmayan hiçbir şeyi değiştirmesine izin verilmez (ve bir kapsayıcı kendi içinde olamaz). Ancak sorgulanan kapsayıcı öğenin kendisi #foo olsaydı tam olarak böyle bir durum olacağını göz önünde bulundurun. #foo[cq-XYZ] özelliği hatalı bir şekilde değiştirilir ve tüm #foo kuralları hatalı bir şekilde uygulanır.

Bunu düzeltmek için, çoklu dolgu aslında iki özellik kullanır: Biri, bir öğeye yalnızca üst öğe tarafından uygulanabilen, diğeri ise bir öğenin kendisine uygulanabileceğidir. İkinci özellik, sözde öğeleri hedefleyen seçiciler için kullanılır.

Önce
@container (width > 300px) {
  #foo,
  #foo::before {
    /* ... */
  }
}
Sonra
@media all {
  #foo:where([cq-XYZ-A~="123"]),
  #foo:where([cq-XYZ-B~="123"])::before {
    /* ... */
  }
}

Bir kapsayıcı ilk özelliği (cq-XYZ-A) hiçbir zaman kendisine uygulamayacağı için ilk seçici, yalnızca kapsayıcı koşullarını karşılayıp farklı bir üst kapsayıcı tarafından uygulanmışsa eşleşir.

Kapsayıcı göreli birimleri

Kapsayıcı sorguları, CSS'nizde kullanabileceğiniz birkaç yeni birim de içerir. Örneğin, en yakındaki uygun üst kapsayıcının genişliğinin ve yüksekliğinin (sırasıyla) %1'i için cqw ve cqh. Bunları desteklemek için birim, CSS Özel Özellikleri kullanılarak calc(...) ifadesine dönüştürülür. Çoklu dolgu, bu özelliklerin değerlerini kapsayıcı öğesindeki satır içi stillerle ayarlar.

Önce
.card {
  width: 10cqw;
  height: 10cqh;
}
Sonra
.card {
  width: calc(10 * --cq-XYZ-cqw);
  height: calc(10 * --cq-XYZ-cqh);
}

Satır içi boyut ve blok boyutu (sırasıyla) için cqi ve cqb gibi mantıksal birimler de vardır. Bunlar biraz daha karmaşıktır. Çünkü satır içi ve blok eksenler, sorgulanan öğe değil, birimi kullanan öğenin writing-mode öğesine göre belirlenir. Çoklu dolgu, bunu desteklemek için writing-mode boyutu üst öğesinden farklı olan her öğeye bir satır içi stil uygular.

/* Element with a horizontal writing mode */
--cq-XYZ-cqi: var(--cq-XYZ-cqw);
--cq-XYZ-cqb: var(--cq-XYZ-cqh);

/* Element with a vertical writing mode */
--cq-XYZ-cqi: var(--cq-XYZ-cqh);
--cq-XYZ-cqb: var(--cq-XYZ-cqw);

Artık birimler eskiden olduğu gibi uygun CSS Özel Mülkü'ne dönüştürülebilir.

Özellikler

Kapsayıcı sorguları ayrıca container-type ve container-name gibi birkaç yeni CSS özelliği de ekler. getComputedStyle(...) gibi API'ler bilinmeyen veya geçersiz özelliklerle kullanılamadığından bunlar da ayrıştırıldıktan sonra CSS Özel Özellikleri'ne dönüştürülür. Bir özellik ayrıştırılamıyorsa (örneğin, geçersiz veya bilinmeyen bir değer içerdiği için) tarayıcının işlemesi için yalnız bırakılır.

Önce
.card {
  container-name: card-container;
  container-type: inline-size;
}
Sonra
.card {
  --cq-XYZ-container-name: card-container;
  --cq-XYZ-container-type: inline-size;
}

Bu özellikler, keşfedildikleri zaman dönüştürülür ve çoklu dolgunun @supports gibi diğer CSS özellikleriyle iyi bir şekilde çalışmasına olanak tanır. Bu işlev, aşağıda açıklandığı şekilde, polyfill'in kullanımıyla ilgili en iyi uygulamaların temelini oluşturur.

Önce
@supports (container-type: inline-size) {
  /* ... */
}
Sonra
@supports (--cq-XYZ-container-type: inline-size) {
  /* ... */
}

Varsayılan olarak CSS Özel Özellikleri devralınır. Örneğin, herhangi bir .card alt öğesi --cq-XYZ-container-name ve --cq-XYZ-container-type değerini alır. Yerel mülkler kesinlikle bu şekilde davranmaz. Bu sorunu çözmek için çoklu dolgu, aşağıdaki kuralı tüm kullanıcı stillerinden önce ekler. Böylece, başka bir kural tarafından kasten geçersiz kılınmadığı sürece her öğenin ilk değerleri alması sağlanır.

* {
  --cq-XYZ-container-name: none;
  --cq-XYZ-container-type: normal;
}

En iyi uygulamalar

Çoğu ziyaretçinin yerleşik kapsayıcı sorgu desteğine sahip tarayıcıları sonradan kullanmaya başlaması beklense de, geri kalan ziyaretçilerinize iyi bir deneyim sunmanız önemlidir.

İlk yükleme sırasında, çoklu dolgunun sayfayı düzenleyebilmesi için yapılması gereken pek çok şey vardır:

  • Çoklu dolgunun yüklenmesi ve başlatılması gerekir.
  • Stil sayfalarının ayrıştırılması ve aktarılması gerekir. Harici bir stil sayfasının ham kaynağına erişmek için herhangi bir API olmadığından, tercihen yalnızca tarayıcı önbelleğinden olsa da eşzamansız olarak yeniden getirilmesi gerekebilir.

Çoklu dolgu, bu endişeleri dikkatle ele almazsa Core Web Vitals verilerinizin geri kalanına yol açabilir.

Ziyaretçilerinize hoş bir deneyim sunmanızı kolaylaştırmak için çoklu dolgu, First Giriş Gecikmesi (FID) ve Cumulative Layout Shift (CLS) özelliğine öncelik verecek şekilde (potansiyel olarak Largest Contentful Paint (LCP)) sağlayacak şekilde tasarlanmıştır. Somut bir şekilde ifade etmek gerekirse, çoklu dolgu, container sorgularınızın ilk boyadan önce değerlendirileceğini garanti etmez. Bu, en iyi kullanıcı deneyimini sunmak için kapsayıcı sorgularının kullanılmasından boyut veya konumu etkilenecek olan tüm içeriklerin, çoklu dolgu CSS'niz yüklenip CSS'ye aktarılıncaya kadar gizlendiğinden emin olmanız gerekir. Bunu yapmanın bir yolu @supports kuralı kullanmaktır:

@supports not (container-type: inline-size) {
  #content {
    visibility: hidden;
  }
}

Ziyaretçiye bir şey olduğunu bildirmek için bunu (gizli) içeriğinizin üzerine kesinlikle yerleştirilmiş bir CSS yükleme animasyonuyla birleştirmeniz önerilir. Bu yaklaşımın tam demosunu burada bulabilirsiniz.

Bu yaklaşım bir dizi nedenden dolayı önerilmektedir:

  • Yalnızca CSS yükleyici yeni tarayıcılara sahip kullanıcıların ek yükünü en aza indirirken, eski tarayıcılar ve yavaş ağları kullananlara hafif geri bildirim sağlar.
  • Yükleyicinin mutlak konumunu visibility: hidden ile birleştirerek düzen kaymasını önlersiniz.
  • Çoklu dolgu yüklendikten sonra bu @supports koşulunun geçişi durdurulur ve içeriğiniz gösterilir.
  • Kapsayıcı sorguları için yerleşik desteğe sahip tarayıcılarda koşul hiçbir zaman geçemez ve bu nedenle sayfa, ilk boyamada beklendiği gibi görüntülenir.

Sonuç

Eski tarayıcılarda kapsayıcı sorguları kullanmak istiyorsanız polyfill'i deneyin. Herhangi bir sorunla karşılaşırsanız sorunu bildirin.

YouTube Create ile geliştireceğiniz muhteşem şeyleri görmek ve deneyimlemek için sabırsızlanıyoruz.

Teşekkür

Dan Cristian Pădure ayda tarafından Unsplash'te hazırlanan hero resim.