Graver dypere inn i containerstilsøk

Kilde node: 1765194

Jeg skrev opp noen tidlige tanker om beholderstilsøk en liten stund tilbake. Det er fortsatt tidlig. De er allerede definert i CSS Containment Module Level 1 spesifikasjon (for øyeblikket i Redaktørutkast-status), men det er fortsatt et par utestående diskusjoner som finner sted.

Den grunnleggende ideen er at vi kan definere en beholder og deretter bruke stiler betinget på dens etterkommere basert på dens beregnede stil.

@container ?  {
  /* conditional styles */
}

Det beste eksemplet jeg har sett så langt er å fjerne kursiv fra noe sånt som , og når de brukes i en kontekst der innholdet allerede er kursivt:

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

Det er den generelle ideen. Men hvis du ikke visste det, holder Miriam Suzanne, som er redaktør av spesifikasjonen, et pågående og grundig sett med personlige notater om forespørsler i containerstil som er offentlig tilgjengelig. Den ble oppdatert her om dagen, og jeg brukte litt tid der inne på å prøve å vikle hodet rundt mer nyanserte aspekter ved stilsøk. Det er uoffisielle greier, men jeg tenkte jeg skulle skrive ned noen ting som skilte seg ut for meg. Hvem vet? Kanskje det er ting vi kan se frem til etter hvert!

Hvert element er en stilbeholder

Vi trenger ikke engang eksplisitt tildele en container-name or container-type å definere en stilbeholder fordi alt er en stilbeholder som standard.

Så du ser det eksemplet ovenfor som fjerner kursiv? Legg merke til at den ikke identifiserer en beholder. Den hopper rett til spørringen ved å bruke style() funksjon. Så hvilken beholder spørres etter? Det kommer til å bli direkte foreldre til elementene motta de anvendte stilene. Og hvis ikke det, så er det det neste nærmeste relative beholder som har forrang.

Jeg liker det. Det er veldig CSS-y for spørringen å søke opp etter et samsvar, og deretter fortsette å boble opp til det finner en samsvarende betingelse.

Det var vanskelig for min lille hjerne å forstå hvorfor vi kan komme unna med en implisitt beholder basert på stiler, men ikke så mye når vi har å gjøre med dimensjonale søk, som size og inline-size. Miriam forklarer det fint:

Dimensjonale søk krever css Begrensning på størrelsen, oppsettet og stilen til beholderen for å forhindre utformingsløkker. Inneslutning er en invasiv ting å bruke bredt, så det var viktig at forfattere hadde nøye kontroll over hvilke elementer som er (eller ikke er) størrelsesbeholdere.

Stilbaserte søk har ikke samme begrensning. Det er allerede ingen måte i CSS for etterkommerstiler å ha innvirkning på de beregnede stilene til en stamfar. Så ingen inneslutning er nødvendig, og det er ingen invasive eller uventede bivirkninger ved å etablere et element som en stil spørringsbeholder.

(Vekt min)

Alt kommer ned til konsekvenser - som det ikke er noen av så langt som at alt er en stilspørringsbeholder rett ut av esken.

  • Hvis en beholder blir funnet: forholdene er løst mot den beholderen.
  • Hvis flere beholdere samsvarer: den nærmeste relative beholderen har forrang.
  • Hvis ingen treff blir funnet: unknown returnert.

Det er det samme "tilgivende" ånd som resten av CSS.

En beholder kan støtte både dimensjons- og stilspørringer

La oss si at vi vil definere en stilspørring uten en eksplisitt container-name:

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

Dette fungerer fordi alle elementer er stilbeholdere, uansett container-type. Det er det som lar oss implisitt spørre etter stiler og stole på den nærmeste matchen. Og dette er helt greit siden, igjen, det er ingen negative bivirkninger når du etablerer stilbeholdere.

Vi må bruke en eksplisitt container-type for dimensjonale spørringer, men ikke så mye for stilspørringer siden hvert element er en stilspørring. Det betyr også at denne beholderen er både en stil og dimensjonsspørring:

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

Ekskluderer en beholder fra å bli spurt

Kanskje vi ikke ønsker at en container skal delta i matchingsprosessen. Det er der det kan være mulig å stille inn container-type: none på et element.

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

Spørringsbeholdere med eksplisitt stil gir mer kontroll over hva som blir spurt

Hvis for eksempel vi skulle skrive en stilspørring for padding , er det ingen pålitelig måte å finne den best samsvarende beholderen, uavhengig av om vi jobber med en eksplisitt navngitt beholder eller nærmeste direkte overordnede. Det er fordi padding er ikke en arvelig eiendom.

Så i slike tilfeller bør vi bruke container-name for å eksplisitt informere nettleseren hvilke containere de kan hente fra. Vi kan til og med gi en beholder flere eksplisitte navn for å få den til å samsvare med flere betingelser:

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

Oh, og container-name godtar et hvilket som helst antall valgfrie og gjenbruk navn på en container! Det er enda mer fleksibilitet når det gjelder å hjelpe nettleseren med å velge når de søker etter treff.

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

Jeg lurer litt på om det også kan betraktes som en "fallback" i tilfelle en container passeres.

Stilspørringer kan kombineres

De or og and operatører lar oss kombinere produkter for å holde ting TØRT:

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

Bytte stiler

Det er litt overlapping mellom beholderstilsøk og arbeid som gjøres for å definere en toggle() funksjon. For eksempel kan vi sykle gjennom to font-style verdier, si italic og normal:

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

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

Kul. Men forslaget til CSS Toggles antyder at toggle() funksjon ville være en enklere tilnærming:

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

Men alt utover denne typen binære brukstilfeller er hvor toggle() er mindre egnet. Stilspørringer er imidlertid gode å gå. Miriam identifiserer tre tilfeller der stilsøk er mer egnet enn en 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;
  }
}

Stilspørringer løser "Custom Property Toggle Hack"

Legg merke til at stilspørringer er en formell løsning for "CSS egendefinert egenskap bytte triks". Der inne setter vi en tom egendefinert egenskap (--foo: ;) og bruk den kommaseparerte reservemetoden for å "veksle" egenskaper på og av når egendefinert egenskap er satt til en reell verdi.

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

Det er superkult, også mye arbeid som stilbeholderspørringer gjør trivielt.

Stilspørringer og CSS-generert innhold

For generert innhold produsert av content tilhører ::before og ::after pseudo-elementer, er den matchende beholderen elementet som innholdet genereres på.

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

Stilspørringer og webkomponenter

Vi kan definere en webkomponent som en beholder og spørre etter stil. For det første har vi av komponenten:


  
… …

Så bruker vi :host pseudo-element som en beholder for å sette en container-nameen container-type, og noen attributter på høyt nivå på den:

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

Elementer inne i kan spørre parametrene til element:

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

Hva blir det neste?

Igjen, alt jeg har notert ned her er basert på Miriams notater, og disse notatene er ikke en erstatning for den offisielle spesifikasjonen. Men de er en indikasjon på hva som diskuteres og hvor ting kan lande i fremtiden. Jeg setter pris på at Miriam koblet sammen en håndfull enestående diskusjoner som fortsatt finner sted som vi kan følge for å holde deg oppdatert:

Tidstempel:

Mer fra CSS triks