Mélyebbre ásni a konténerstílusú lekérdezéseket

Forrás csomópont: 1765194

Felírtam néhányat korai gondolatok a konténerstílusú lekérdezésekről kicsit vissza. Még korai napok vannak. Ezeket már meghatározták a CSS Containment Module Level 1 specifikáció (jelenleg Szerkesztői vázlat státuszban van), de még mindig zajlik néhány kiemelkedő megbeszélés.

Az alapötlet az, hogy definiálhatunk egy tárolót, majd feltételesen alkalmazhatunk stílusokat a leszármazottaira a kiszámított stílus alapján.

@container ?  {
  /* conditional styles */
}

A legjobb példa, amit eddig láttam, a dőlt betű eltávolítása valami hasonlóról , és ha olyan kontextusban használják őket, ahol a tartalom már dőlt betűs:

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;
  }
}

Ez az általános elképzelés. De ha nem tudná, Miriam Suzanne, aki a specifikáció szerkesztője, folyamatos és alapos gyűjteményt vezet személyes megjegyzések a konténerstílusú lekérdezésekhez amely nyilvánosan elérhető. A minap frissítették, és eltöltöttem egy kis időt ott, és megpróbáltam a stíluslekérdezések árnyaltabb aspektusai körül járni. Ez nem hivatalos dolog, de gondoltam leírok néhány dolgot, ami feltűnt számomra. Ki tudja? Talán ez olyan dolog, amire végül is várhatunk!

Minden elem egy stílustároló

Még csak nem is kell kifejezetten hozzárendelnünk a container-name or container-type stílustároló meghatározásához, mert alapértelmezés szerint minden stílustároló.

Tehát látja a fenti példát, amely eltávolítja a dőlt betűket? Figyelje meg, hogy nem azonosít tárolót. Ez közvetlenül a lekérdezéshez ugrik a segítségével style() funkció. Tehát melyik tárolót kérdezi? Ez lesz a az elemek közvetlen szülője az alkalmazott stílusok fogadása. És ha nem az, akkor az a legközelebbi relatív konténer az elsőbbséget élvez.

Ez tetszik. Nagyon CSS-y, hogy a lekérdezés egyezést keressen, majd folytassa a buborékolást, amíg meg nem találja a megfelelő feltételt.

Az én kis agyamnak nehéz volt megértenie, hogy miért lehet megúszni egy stílusokon alapuló implicit tárolót, de nem annyira, ha dimenziós lekérdezésekkel foglalkozunk, mint pl. size és a inline-size. Miriam szépen elmagyarázza:

A dimenziós lekérdezésekhez css szükséges elhatárolás a tároló méretére, elrendezésére és stílusára az elrendezési hurkok elkerülése érdekében. Az elzárás egy invazív dolog, amelyet széles körben kell alkalmazni, ezért fontos volt, hogy a szerzők gondosan ellenőrizzék, milyen méretű tárolók (vagy nem).

A stílusalapú lekérdezésekre nem vonatkoznak ugyanazok a korlátozások. A CSS-ben már nincs mód arra, hogy a leszármazott stílusok hatással legyenek az ősök számított stílusaira. Tehát nincs szükség elzárásra, és nincsenek invazív vagy váratlan mellékhatások egy elemnek a stílusú lekérdezési tároló.

(Kiemelés az enyém)

Minden a következményeken múlik – amelyekből nincs semmi, mivel minden egy stílusos lekérdezési konténer, már a dobozból.

  • Ha egy tárolót talál: a feltételek megoldódnak az adott tárolóval szemben.
  • Ha több tároló egyezik: a legközelebbi relatív tároló élvez elsőbbséget.
  • Ha nem található egyezés: unknown vissza.

Ez ugyanaz „megbocsátó” szellem, mint a CSS többi része.

Egy tároló támogathatja a méret- és stíluslekérdezéseket is

Tegyük fel, hogy egy stíluslekérdezést szeretnénk explicit nélkül meghatározni container-name:

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

Ez azért működik, mert minden elem stílustároló, nem számít a container-type. Ez az, ami lehetővé teszi számunkra, hogy implicit módon lekérdezzünk stílusokat, és a legközelebbi egyezésre hagyatkozzunk. És ez teljesen rendben van, mivel ismét nincsenek káros mellékhatások a stílusos konténerek létrehozásakor.

Explicit kifejezést kell használnunk container-type dimenziós lekérdezésekhez, de stíluslekérdezésekhez nem annyira, mivel minden elem stíluslekérdezés. Ez azt is jelenti, hogy ez a konténer egyszerre stílus és a dimenziós lekérdezés:

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

Egy tároló kizárása a lekérdezésből

Talán nem akarjuk, hogy egy konténer részt vegyen az egyeztetési folyamatban. Ott lehet beállítani container-type: none egy elemen.

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

Az explicit stílusú lekérdezési tárolók jobban szabályozhatják a lekérdezéseket

Ha mondjuk stíluslekérdezést írnánk a számára padding , nincs megbízható módszer a legjobban illeszkedő tároló meghatározására, függetlenül attól, hogy kifejezetten elnevezett tárolóval vagy a legközelebbi közvetlen szülővel dolgozunk. Azért mert padding nem örökölt ingatlan.

Tehát ilyen esetekben használnunk kell container-name hogy egyértelműen tájékoztassa a böngészőt, hogy mely tárolókból tud lekérni. Akár több explicit nevet is adhatunk egy tárolónak, hogy több feltételnek megfeleljen:

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

Ja, és container-name tetszőleges számú választható és újrahasználható nevek egy konténerhez! Ez még nagyobb rugalmasságot jelent, amikor arról van szó, hogy segítse a böngészőt a választásban, amikor egyezéseket keres.

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

Azon tűnődöm, hogy ez is „tartaléknak” tekinthető-e abban az esetben, ha egy konténert áthaladnak.

A stíluslekérdezések kombinálhatók

A or és a and Az operátorok lehetővé teszik számunkra, hogy a wueréket kombináljuk, hogy a dolgok SZÁRAZON maradjanak:

@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. */
}

Stílusok váltása

Van egy kis átfedés a konténerstílusú lekérdezések és a a meghatározása érdekében végzett munka toggle() funkció. Például áttekerhetünk kettőn font-style értékek, mondjuk italic és a normal:

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

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

Menő. A CSS Toggles-re vonatkozó javaslat azonban azt sugallja, hogy a toggle() A függvény egyszerűbb megközelítés lenne:

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

De az effajta bináris felhasználási eseteken túl minden hol van toggle() kevésbé alkalmas. A stíluslekérdezések azonban megfelelőek. A Miriam három olyan esetet azonosít, ahol a stíluslekérdezések alkalmasabbak, mint a 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;
  }
}

A stíluslekérdezések megoldják a „Custom Property Toggle Hack” problémát

Vegye figyelembe, hogy a stíluslekérdezések formális megoldást jelentenek a „CSS egyéni tulajdonságok váltási trükkje”. Ott beállítunk egy üres egyéni tulajdonságot (--foo: ;), és használja a vesszővel elválasztott tartalék módszert a tulajdonságok „be- és kikapcsolásához”, amikor az egyéni tulajdonság valós értékre van állítva.

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. */
}

Ez nagyon klassz, és rengeteg munka, amit a konténerlekérdezések triviálissá tesznek.

Stíluslekérdezések és CSS által generált tartalom

A generált tartalomhoz, amelyet a content tulajdona ::before és a ::after pszeudoelemek esetén az egyező tároló az az elem, amelyen a tartalom létrejön.

.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;
  }
}

Stíluslekérdezések és webes összetevők

Egy webkomponenst tárolóként határozhatunk meg, és stílus szerint lekérdezhetjük. Először is megvan a az összetevőből:


  
… …

Ezután használjuk a :host pszeudo-elem tárolóként a beállításához container-nameEgy container-type, és néhány magas szintű attribútum rajta:

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

Elemek a belsejében lekérdezheti a paramétereit elem:

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

Mi a következő lépés?

Ismét minden olyan dolog, amit ide feljegyeztem, Miriam feljegyzésein alapul, és ezek a megjegyzések nem helyettesítik a hivatalos specifikációt. De ezek jelzik, hogy miről beszélnek, és hol érhetnek el a dolgok a jövőben. Nagyra értékelem, hogy Miriam egy maroknyi kiemelkedő megbeszélést kapcsolt össze, amelyek még mindig zajlanak, és követhetjük, hogy naprakészek maradjunk:

Időbélyeg:

Még több CSS trükkök