Dieper graven in vragen over containerstijlen

Bronknooppunt: 1765194

ik heb wat opgeschreven vroege gedachten over query's in containerstijl een tijdje terug. Het is nog vroeg. Ze zijn al gedefinieerd in de Specificatie CSS Containment Module niveau 1 (momenteel in Editor's Draft-status) maar er vinden nog een aantal openstaande discussies plaats.

Het basisidee is dat we een container kunnen definiëren en vervolgens stijlen voorwaardelijk kunnen toepassen op zijn afstammelingen op basis van de berekende stijl.

@container ?  {
  /* conditional styles */
}

Het beste voorbeeld dat ik tot nu toe heb gezien, is het verwijderen van cursief uit iets als , en wanneer ze worden gebruikt in een context waarin de inhoud al cursief is:

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

Dat is het algemene idee. Maar als je het nog niet wist, Miriam Suzanne, die redacteur is van de specificatie, houdt een doorlopende en grondige reeks van persoonlijke opmerkingen over zoekopdrachten in containerstijl dat openbaar is. Het is onlangs bijgewerkt en ik heb daar enige tijd doorgebracht om mijn hoofd te wikkelen rond meer genuanceerde aspecten van stijlvragen. Het zijn onofficiële dingen, maar ik dacht dat ik wat dingen zou opschrijven die me opvielen. Wie weet? Misschien zijn het dingen waar we uiteindelijk naar uit kunnen kijken!

Elk element is een stijlcontainer

We hoeven niet eens expliciet a toe te wijzen container-name or container-type om een ​​stijlcontainer te definiëren omdat alles standaard een stijlcontainer is.

Dus je ziet dat voorbeeld hierboven dat cursief verwijdert? Merk op dat het geen container identificeert. Het springt rechtstreeks naar de query met behulp van de style() functie. Dus, welke container wordt bevraagd? Het wordt de directe ouder van de elementen het ontvangen van de toegepaste stijlen. En zo niet, dan is het dat wel de volgende dichtstbijzijnde relatieve container dat heeft voorrang.

Dat vind ik leuk. Het is erg CSS-y voor de zoekopdracht om naar een overeenkomst te zoeken en vervolgens door te gaan met opborrelen totdat er een overeenkomende voorwaarde wordt gevonden.

Het was moeilijk voor mijn kleine brein om te begrijpen waarom we kunnen wegkomen met een impliciete container op basis van stijlen, maar niet zozeer als we te maken hebben met dimensionale vragen, zoals size en inline-size. Miriam legt het mooi uit:

Dimensionale queries vereisen css containment op de grootte, lay-out en stijl van de container om lay-outlussen te voorkomen. Inperking is een invasief iets om breed toe te passen, dus het was belangrijk dat auteurs zorgvuldige controle hadden over welke elementen wel of niet groottecontainers zijn.

Op stijl gebaseerde query's hebben niet dezelfde beperking. Er is al geen manier in CSS voor stijlen van afstammelingen om invloed uit te oefenen op de berekende stijlen van een voorouder. Er is dus geen insluiting vereist en er zijn geen invasieve of onverwachte bijwerkingen bij het vaststellen van een element als een stijlquerycontainer.

(benadruk de mijne)

Het komt allemaal neer op consequenties - waarvan er geen zijn voor zover alles een stijlquery-container is, direct uit de doos.

  • Als een container wordt gevonden: voorwaarden worden opgelost voor die container.
  • Als meerdere containers overeenkomen: de dichtstbijzijnde relatieve container heeft voorrang.
  • Als er geen overeenkomsten worden gevonden: unknown teruggekeerd.

Dat is hetzelfde "vergevingsgezinde" geest als de rest van CSS.

Een container kan zowel dimensionale als stijlquery's ondersteunen

Laten we zeggen dat we een stijlquery willen definiëren zonder expliciet container-name:

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

Dit werkt omdat alle elementen zijn stijlcontainers, ongeacht de container-type. Dat is wat ons in staat stelt impliciet stijlen te doorzoeken en te vertrouwen op de dichtstbijzijnde overeenkomst. En dit is helemaal prima, want nogmaals, er zijn geen nadelige bijwerkingen bij het opzetten van stijlcontainers.

We moeten een expliciet gebruiken container-type voor dimensionale query's, maar niet zozeer voor stijlquery's, aangezien elk element een stijlquery is. Dat betekent ook dat deze container zowel een stijl is en dimensionale vraag:

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

Een container uitsluiten van bevraging

Misschien willen we niet dat een container meedoet aan het matchingsproces. Dat is waar het misschien mogelijk is om in te stellen container-type: none op een element.

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

Querycontainers in expliciete stijl bieden meer controle over wat er wordt opgevraagd

Als we bijvoorbeeld een stijlquery zouden schrijven voor padding , is er geen betrouwbare manier om de best passende container te bepalen, ongeacht of we werken met een container met een expliciete naam of de dichtstbijzijnde directe ouder. Dat is omdat padding is geen erfelijk bezit.

Dus in die gevallen zouden we moeten gebruiken container-name om de browser expliciet te laten weten uit welke containers ze kunnen halen. We kunnen een container zelfs meerdere expliciete namen geven zodat deze aan meer voorwaarden voldoet:

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

Oh, en container-name accepteert een willekeurig aantal optionele en herbruikbare namen voor een container! Dat is nog meer flexibiliteit als het erom gaat de browser te helpen een keuze te maken bij het zoeken naar overeenkomsten.

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

Ik vraag me een beetje af of dat ook als een "terugval" kan worden beschouwd in het geval dat er een container wordt gepasseerd.

Stijlquery's kunnen worden gecombineerd

De or en and operators stellen ons in staat om wueries te combineren om dingen DROOG te houden:

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

Wisselende stijlen

Er is een kleine overlap tussen query's in containerstijl en er wordt gewerkt aan het definiëren van a toggle() functie. We kunnen er bijvoorbeeld twee doorlopen font-style waarden, zeg maar italic en normal:

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

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

Koel. Maar het voorstel voor CSS Toggles suggereert dat de toggle() functie zou een eenvoudiger benadering zijn:

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

Maar alles buiten dit soort binaire use-cases is waar toggle() is minder geschikt. Stijlvragen zijn echter goed om te gebruiken. Miriam identificeert drie gevallen waarin stijlquery's geschikter zijn dan 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;
  }
}

Stijlquery's lossen de "Custom Property Toggle Hack" op

Merk op dat stijlquery's een formele oplossing zijn voor de "Truc voor het wisselen van CSS-aangepaste eigenschappen". Daarin stellen we een lege aangepaste eigenschap in (--foo: ;) en gebruik de door komma's gescheiden fallback-methode om eigenschappen in en uit te schakelen wanneer de aangepaste eigenschap is ingesteld op een reële waarde.

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

Dat is super cool, ook een hoop werk dat stijlcontainerquery's triviaal maakt.

Stijlquery's en door CSS gegenereerde inhoud

Voor gegenereerde inhoud geproduceerd door de content eigendom van ::before en ::after pseudo-elementen, de bijpassende container is het element waarop de inhoud wordt gegenereerd.

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

Stijlquery's en webcomponenten

We kunnen een webcomponent definiëren als een container en deze op stijl doorzoeken. Ten eerste hebben we de van het onderdeel:


  
… …

Dan gebruiken we de :host pseudo-element als een container om een container-name, een container-type, en enkele attributen op hoog niveau erop:

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

Elementen binnen de kan de parameters van de element:

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

What’s next?

Nogmaals, al het materiaal dat ik hier heb opgeschreven is gebaseerd op Miriam's aantekeningen, en die aantekeningen zijn geen vervanging voor de officiële specificaties. Maar ze zijn een indicatie van wat er wordt besproken en waar dingen in de toekomst kunnen landen. Ik waardeer het dat Miriam een ​​handvol openstaande discussies heeft gekoppeld die nog steeds plaatsvinden en die we kunnen volgen om op de hoogte te blijven:

Tijdstempel:

Meer van CSS-trucs