Front-end development + UX + Accessibility

CSS Container Size Queries (in Norwegian)

To bentobox måltider.
The food in a bentobox fits itself itto whatever shape the surrounding box has.

Webutviklere har forespurt container queries i snart 10 år, og nå er de endelig her! For øyeblikket kan vi kun kjøre queries på størrelse (size). Og per idag (05.10.2022) er det kun Chrome 106 og Safari 16 som har støtte.

Can I Use har den beste oversikten over hvilke nettlesere som støtter hva til en hver tid.

Hva er en “container query”? #

Med container queries kan vi nå spørre ett enkelt element om en rekke verdier og egenskaper, og sette bestemte CSS regler basert på det. Dette blir kalt en container kontekst. I denne artikkelen vil jeg kun fokusere på inline-size egenskapen, siden det er den eneste som har støtte i nettlesere nå.

Dersom du er vant med CSS Grid eller Flexbox, så vil du kanskje kjenne igjen kontekst konseptet med at HTML elementer sin layout blir bestemt på foreldre-elementet, som i display: flex og display: grid.

Lag en container #

For en container size query, så er de magiske ordene:

container-type: inline-size;

OBS! Se opp for artikler hvor contain blir brukt. Det er basert på tidligere versjoner av utkastet for container queries, da parameteret contain ble brukt.

Referer til en container #

Dette gjøres veldig likt hvordan vi bruker media queries, men istedenfor å måle bredden på selve nettleseren, kan vi nå måle bredden på et HTML element.

Ved å kun måle bredden på elementet, kan det samme elementet ha forskjellig layout og stil avhengig av hvor god plass det har på siden.

En tredjedel og to tredjedels layout med et HTML element gjentatt flere ganger i begge kolonner.
Hver modul referer til foreldre-containeren.

Hvilken container?! #

Hvordan vet CSS og nettleseren hvilken container den skal måle og sette kontekst ut ifra?

En kort-modul som sjekker bredden på en foreldre-modul.
`.card` ligger i en container query som sjekker nærmeste forelder.

Eksempel #

Her er et eksempel på et card komponent:

<div class="card">
<div class="card__media"></div>
<div class="card__content"></div>
</div>

Når vi skal bruke container queries så trenger vi å legge til ett “wrapper” element. Dette er fordi vi kan kun sette stiler på element som er inni foreldreelementet. Så dersom vi ønsker å sette stil til selve .card elementet, trenger det en forelder.

<div class="card-wrapper">
<!-- Legg til wrapper -->
<div class="card">
<div class="card__media"></div>
<div class="card__content"></div>
</div>
</div>

Sette stil #

Og nå kan vi kose oss med CSS!

.card-wrapper {
container-type: inline-size; /* Sett kontekst */
}

/* Standard layout */
.card {}
.card__media {}
.card__content {}

/* Design når .cardwrapper er over 480px bred */
@container (min-width: 480px) {
.card {}
.card__media {}
.card__content {}
}

Når vi skriver @container queries, så er det tilnærmet identisk med å skrive @media queries. Men vi må huske å også fortelle nettleseren hvilket element som er containeren, som vi gjør ved å spesifisere container-type: inline-size på den CSS klassen.

Valgfritt: container-name #

Det er også mulig å gi containeren ett navn, og det navnet kan refereres til fra en container query. Dette kan være greit når det blir mange queries å holde orden i, eller at det er nøstet langt nedi hierarkiet.

Med konteksten på plass, så kan vi skrive queries som ser ut som vanlige media-queries. Men istedenfor å sjekke bredden på nettleseren, så sjekker den bredden på elementet med klassen .container i dette eksemplet.

Så kan vi skrive @container queryet som tidligere, men med navnet på containeren som ett ekstra parameter.

.wrapper {
container-type: inline-size;
container-name: sidebar; /* Legg til navn */
}

.card {
display: grid;
grid-template-columns: 1fr;
}

/* Se etter container med navn "sidebar" */
@container sidebar (min-width: 400px) {
.card {
grid-template-columns: 2fr 1fr;
}
}

Når skal jeg bruke container? #

Mye av det container queries gjør kan løses med Flexbox og CSS Grid. Men layout og kolonner er ikke det eneste som container query lar oss endre. Vi kan også inkludere andre design element, for eksempel:

Fordeler for oss utviklere #

Vi er vant med å bruke modifier klasser (”M” i BEM) for å gi et komponent forskjellige uttrykk. Nå har vi muligheten til å la størrelsen på komponentet gjøre det samme. Vi slipper å bruke JavaScript løsninger for å dynamisk legge til og trekke fra klasser i body og andre steder.

Demonstrasjon #

NB! Dette virker kun i Chrome 106 og Safari 16 og oppover.

CodePen #

Det er best å åpne live kodeeksemplet direkte i CodePen: https://codepen.io/eystein/pen/wvjGejM

See the Pen Container size queries by Eystein Mack Alnaes (@eystein) on CodePen.

Skjermbilde #

Samme komponent, samme HTML, samme CSS, i 3 forskjellige format.

En webside med 3 rader, med hendholdsvis 3, 2, og 1 komponent per rad.
Samme `.card` med forskjellig layout og design avhengig av sin egen bredde.

Video #

Videoen viser hvordan breakpoints i to container queries gir forskjellige design på et komponent, uten å endre bredden på nettleseren. I videoen viser jeg tre ting:

  1. Endrer størrelsen på det nederste komponentet, som veksler mellom de 3 designene.
  2. Legger til 2 komponenter i rad to, som tilpasser seg den nye størrelsen.
  3. Sletter 1 komponent fra den øverste raden, som tilpasser seg den nye størrelsen.

Oppsummering #

  1. Bruk Chrome 106 eller Safari 16 og oppover.
  2. Sett container-type: inline-size; egenskapen på foreldre-elementet.
  3. Skriv CSS endringene i en query: @container (min-width: 480px) {…}

← Home