Konteyner Stili Sorgularını Daha Derine İnmek

Kaynak Düğüm: 1765194

biraz yazdım Konteyner tarzı sorgularla ilgili ilk düşünceler biraz önce. Henüz erken günler. Bunlar zaten şurada tanımlanmış: CSS Sınırlama Modülü Düzey 1 spesifikasyonu (şu anda Editörün Taslak durumunda) ancak hala birkaç önemli tartışma sürüyor.

Temel fikir, bir kapsayıcı tanımlayabilmemiz ve ardından onun hesaplanan stiline dayalı olarak stilleri onun alt öğelerine koşullu olarak uygulayabilmemizdir.

@container ?  {
  /* conditional styles */
}

Şu ana kadar gördüğüm en iyi örnek, şunun gibi bir şeyden italik yazıların kaldırılmasıdır: , , ve içeriğin zaten italik olduğu bir bağlamda kullanıldığında:

em, i, q {
  font-style: italic; /* default UA behavior */
}

/* When the container's font-style is italic, remove italics from these elements. */
@container style(font-style: italic) {
  em, i, q {
    font-style: normal;
  }
}

Genel fikir bu. Ancak bilmiyorsanız, spesifikasyonun editörü Miriam Suzanne, sürekli ve kapsamlı bir dizi rapor hazırlıyor. Kapsayıcı tarzı sorgularla ilgili kişisel notlar bu kamuya açık bir bilgidir. Geçen gün güncellendi ve stil sorgularının daha incelikli yönlerine kafa yormaya çalışmak için biraz zaman harcadım. Bunlar resmi olmayan şeyler ama dikkatimi çeken bazı şeyleri not almam gerektiğini düşündüm. Kim bilir? Belki de sonunda sabırsızlıkla bekleyebileceğimiz şeylerdir!

Her öğe bir stil kabıdır

Açıkça bir atama yapmamıza bile gerek yok. container-name or container-type bir stil kabı tanımlamak için çünkü her şey varsayılan olarak bir stil kabıdır.

Peki, yukarıdaki italikleri kaldıran örneği görüyor musunuz? Bir konteyneri tanımlamadığına dikkat edin. kullanarak doğrudan sorguya atlar. style() işlev. Peki hangi kapsayıcı sorgulanıyor? Bu olacak elementlerin doğrudan ebeveyni uygulanan stilleri almak. Ve eğer bu değilse, o zaman bir sonraki en yakın akraba konteyner bu öncelik taşır.

Bunu sevdim. Sorgunun bir eşleşme araması ve ardından eşleşen bir koşul bulana kadar kabarmaya devam etmesi oldukça CSS'ye benzer.

Küçük beynim için, stillere dayalı örtülü bir kapsayıcıdan neden kurtulabildiğimizi anlamak zordu ama boyutsal sorgularla uğraşırken o kadar da değil. size ve inline-size. Miriam bunu çok güzel açıklıyor:

Boyutlu sorgular css gerektirir kapsama Düzen döngülerini önlemek için kabın boyutuna, düzenine ve stiline göre değişiklik yapın. Sınırlama, geniş çapta uygulanması istilacı bir şeydir, bu nedenle yazarların hangi öğelerin kapsayıcı boyutta olduğu (veya olmadığı) üzerinde dikkatli bir kontrole sahip olması önemliydi.

Stil tabanlı sorgular aynı sınırlamaya sahip değildir. CSS'de, soyundan gelen stillerin, ataların hesaplanan stilleri üzerinde bir etkiye sahip olmasının hiçbir yolu zaten yoktur. Dolayısıyla hiçbir sınırlamaya gerek yoktur ve bir unsurun bir bileşen olarak oluşturulmasında istilacı veya beklenmedik yan etkiler yoktur. stil sorgu kapsayıcısı.

(benimki vurgula)

Her şey sonuçlara bağlı - her şeyin kutudan çıktığı gibi bir stil sorgu kapsayıcısı olması dışında bunların hiçbiri yok.

  • Bir konteyner bulunursa: Koşullar bu konteynere göre çözümlenir.
  • Birden fazla kapsayıcı eşleşirse: en yakın ilgili kapsayıcı öncelikli olur.
  • Hiçbir eşleşme bulunamazsa: unknown iade.

Bu aynısı CSS'nin geri kalanı gibi "bağışlayıcı" ruh.

Bir kapsayıcı hem boyut hem de stil sorgularını destekleyebilir

Diyelim ki açık bir ifade olmadan bir stil sorgusu tanımlamak istiyoruz. container-name:

@container style(font-style: italic) {
  em {
    font-style: normal;
  }
}

Bu işe yarıyor çünkü tüm öğeler stil kaplarıdırne olursa olsun container-type. Stilleri dolaylı olarak sorgulamamıza ve en yakın eşleşmeye güvenmemize olanak tanıyan şey budur. Ve bu tamamen iyidir, çünkü yine stil kapları oluştururken hiçbir olumsuz yan etki yoktur.

Açık bir ifade kullanmak zorundayız container-type boyutlu sorgular için, ancak her öğe bir stil sorgusu olduğundan stil sorguları için pek geçerli değil. Bu aynı zamanda bu kabın hem bir stil hem de bir stil olduğu anlamına gelir ve boyutlu sorgu:

.card-container {
  container: card / inline-size; /* implictly a style query container as well */
}

Bir kapsayıcının sorgulanmasını hariç tutmak

Belki de bir konteynerin eşleştirme sürecine katılmasını istemiyoruz. Ayarlamanın mümkün olabileceği yer burasıdır container-type: none bir element üzerinde.

.some-element {
  container-type: none;
}

Açık stildeki sorgu kapsayıcıları, neyin sorgulanacağı konusunda daha fazla kontrol sağlar

Diyelim ki bir stil sorgusu yazacak olsaydık padding Açıkça adlandırılmış bir kapsayıcıyla mı yoksa en yakın doğrudan üst öğeyle mi çalıştığımıza bakılmaksızın, en iyi eşleşen kapsayıcıyı belirlemenin güvenilir bir yolu yoktur. O yüzden padding miras kalan bir mülk değildir.

Yani bu durumlarda şunu kullanmalıyız: container-name tarayıcıya hangi kapsayıcılardan bilgi alabileceklerini açıkça bildirmek için. Hatta bir konteynere daha fazla koşulla eşleşmesi için birden fazla açık ad bile verebiliriz:

.card {
  container-name: card layout theme;
}

Oh, ve container-name herhangi bir sayıda isteğe bağlı kabul eder ve yeniden kullanılabilir bir konteyner için isimler! Bu, tarayıcının eşleşme ararken seçim yapmasına yardımcı olma konusunda daha da fazla esneklik demektir.

.theme {
  container-name: theme;
}
.grid {
  container-name: layout;
}
.card {
  container-name: card layout theme;
}

Bir konteynerin atlanması durumunda bunun bir "geri dönüş" olarak da değerlendirilip değerlendirilemeyeceğini merak ediyorum.

Stil sorguları birleştirilebilir

The or ve and operatörler işleri KURU tutmak için sıkıntıları birleştirmemize izin veriyor:

@container bubble style(--arrow-position: start start) or style(--arrow-position: end start) {
  .bubble::after {
    border-block-end-color: inherit;
    inset-block-end: 100%;
  }
}

/* is the same as... */
@container bubble style(--arrow-position: start start) {
  /* etc. */
}
@container bubble style(--arrow-position: end start) {
  /* etc. */
}

Stilleri değiştirme

Kapsayıcı stili sorguları arasında küçük bir örtüşme var ve tanımlamak için çalışmalar yapılıyor toggle() işlev. Örneğin iki tane arasında geçiş yapabiliriz font-style değerler diyelim italic ve normal:

em, i, q {
  font-style: italic;
}

@container style(font-style: italic) {
  em, i, q {
    font-style: normal;
  }
}

Serin. Ancak CSS Geçişleri önerisi şunu gösteriyor: toggle() işlevi daha basit bir yaklaşım olacaktır:

em, i, q {
  font-style: toggle(italic, normal);
}

Ancak bu tür ikili kullanım durumunun ötesindeki her şey, toggle() daha az uygundur. Stil sorguları yine de hazırdır. Miriam, stil sorgularının bir stil sorgusundan daha uygun olduğu üç örneği tanımlar. toggle():

/* When font-style is italic, apply background color. */
/* Toggles can only handle one property at a time. */
@container style(font-style: italic) {
  em, i, q {
    background: lightpink;
  }
}

/* When font-style is italic and --color-mode equals light */
/* Toggles can only evaluate one condition at a time */
@container style((font-style: italic) and (--color-mode: light)) {
  em, i, q {
    background: lightpink;
  }
}

/* Apply the same query condition to multiple properties */
/* Toggles have to set each one individually as separate toggles */
@container style(font-style: italic) {
  em, i, q {
    /* clipped gradient text */
    background: var(--feature-gradient);
    background-clip: text;
    box-decoration-break: clone;
    color: transparent;
    text-shadow: none;
  }
}

Stil sorguları "Özel Özellik Geçiş Hack" sorununu çözüyor

Stil sorgularının resmi bir çözüm olduğuna dikkat edin. “CSS özel özellik geçiş numarası”. Burada boş bir özel özellik belirledik (--foo: ;) ve özel özellik gerçek bir değere ayarlandığında özellikleri açıp kapatmak için virgülle ayrılmış geri dönüş yöntemini kullanın.

button {
  --is-raised: ; /* off by default */
  
  border: 1px solid var(--is-raised, rgb(0 0 0 / 0.1));
  box-shadow: var(
    --is-raised,
    0 1px hsl(0 0% 100% / 0.8) inset,
    0 0.1em 0.1em -0.1em rgb(0 0 0 / 0.2)
  );
  text-shadow: var(--is-raised, 0 -1px 1px rgb(0 0 0 / 0.3));
}

button:active {
  box-shadow: var(--is-raised, 0 1px 0.2em black inset);
}

#foo {
  --is-raised: initial; /* turned on, all fallbacks take effect. */
}

Bu çok hoş, aynı zamanda stil konteyner sorgularının önemsiz hale getirilmesi için yapılan çok fazla iş var.

Stil sorguları ve CSS tarafından oluşturulan içerik

tarafından üretilen oluşturulan içerik için content mülkiyet ::before ve ::after Sözde öğelerde eşleşen kapsayıcı, içeriğin oluşturulduğu öğedir.

.bubble {
  --arrow-position: end end;
  container: bubble;
  border: medium solid green;
  position: relative;
}

.bubble::after {
  content: "";
  border: 1em solid transparent;
  position: absolute;
}

@container bubble style(--arrow-position: end end) {
  .bubble::after {
    border-block-start-color: inherit;
    inset-block-start: 100%;
    inset-inline-end: 1em;
  }
}

Stil sorguları ve web bileşenleri

Bir web bileşenini konteyner olarak tanımlayıp stile göre sorgulayabiliriz. Öncelikle elimizde bileşenin:


  
… …

Sonra kullanırız :host sözde öğeyi ayarlamak için bir kap olarak kullanın container-name, container-typeve bununla ilgili bazı üst düzey özellikler:

:host {
  container: media-host / inline-size;
  --media-location: before;
  --media-style: square;
  --theme: light;
}

İçindeki elementler parametrelerini sorgulayabilir eleman:

@container media-host style(--media-style: round) {
  [part='img'] {
    border-radius: 100%;
  }
}

Sıradaki ne?

Tekrar ediyorum, buraya not ettiğim her şey Miriam'ın notlarına dayanmaktadır ve bu notlar resmi spesifikasyonların yerine geçmez. Ancak bunlar neyin tartışıldığının ve işlerin gelecekte nereye varabileceğinin bir göstergesi. Miriam'ın, gelişmelerden haberdar olmak için takip edebileceğimiz, hâlâ devam eden bir avuç önemli tartışmayı birbirine bağlamasını takdir ediyorum:

Zaman Damgası:

Den fazla CSS Püf Noktaları