Hvorfor container queries
En komponent kan have lidt plads i en sidebar og meget plads i hovedindholdet, selv om browserbredden er den samme. Container queries gør det muligt at tilpasse komponenten til den plads, dens omgivende container giver den.
Forløbet handler om size queries. Slides nævner også navngivning, style queries og scroll-state queries; se MDN’s oversigt for de øvrige muligheder.
Åbn komponenteksemplet fra slides, og undersøg, hvordan samme komponent bruges i forskellige bredder.
Containment og syntax
Hvis en regel både målte og ændrede et elements egen bredde, kunne den skabe en cirkel: en bredde over 400px udløser 300px, som derefter udløser en større bredde igen.
Size containment adskiller containerens størrelsesberegning fra dens indhold på den relevante akse. En size query bruger en egnet ancestor-container; den måler ikke det element, reglen styler. I card-eksemplet giver en wrapper derfor kortet den størrelse, det skal reagere på.
<div class="card-wrapper"> <article class="card"> <h2>Card heading</h2> <p>Indhold i kortet</p> </article></div>.card-wrapper { container-type: inline-size;}inline-size bruges her til at måle bredden i normal vandret skriveretning, mens højden fortsat kan følge indholdet. size indebærer containment på begge akser og kræver derfor også, at højden får plads på anden vis.
En ekstra div er praktisk i øvelsen, men en eksisterende wrapper kan også bruges. Kortet kan ikke bruge sig selv som size-query-container; det kan derimod godt styles ud fra en container længere oppe i dokumentet.
Media vs container
En bredde-query med @media måler viewporten. En bredde-query med @container måler en egnet container omkring det element, der styles. Media queries kan også undersøge andre forhold, fx brugerpræferencer; de er stadig nyttige til det overordnede layout.
I demoen kan du skifte mellem query-typerne og slå en sidebar til. Hold browserbredden fast, og se, om kortet reagerer på den ændrede plads.
Container-syntax i praksis
Her skifter et kort fra én til to kolonner, når wrapperen har plads:
.card-wrapper { container-type: inline-size;}
.card { display: grid; gap: 1rem;
@container (width > 640px) { grid-template-columns: 2fr 3fr; }}Uden et navn finder queryen den nærmeste ancestor, som kan besvare størrelsesforespørgslen. Bemærk forskellen på at deklarere containeren og at style dens indhold.
Farver og nesting
I denne øvelse er hvert li allerede en inline-size-container. Lad dets span skifte baggrund, når der er mere plads. Tilføj og fjern bokse med knapperne: containerbredden ændres, selv om browseren beholder samme størrelse.
En query kan nestes direkte i den selector, den gælder for:
span { background: var(--color-1);
@container (width > 75px) { background: var(--color-2); }
@container (width > 150px) { background: var(--color-3); }}Når begge betingelser er opfyldt, vinder den senere baggrundsregel her. Prøv flere grænser med øvelsens farvevariable. Se også Nesting.
Øvelse 1
Card med wrapper og :has()
:has(img) vælger de kort, der indeholder et billede. Container queryen afgør derefter, hvornår det valgte kort har plads til to kolonner. Indhold og tilgængelig plads bliver dermed to forskellige betingelser.
- Tilføj
<div class="card-wrapper">rundt om.cardi HTML. - Giv wrapperen
container-type: inline-size. - Lad kortet med billede bruge to kolonner, når wrapperen er bredere end
300px.
.card:has(img) { display: grid; gap: 1rem;
@container (width > 300px) { grid-template-columns: 1fr 3fr; }}I slides bruges også 600px og 2fr 3fr som eksempel. Følg her øvelsens 300px og udgangspunktet 1fr 3fr, så det passer til editoren og dens checks. Mekanikken er den samme.
Navngivne containere
Et navn gør det muligt at vælge en bestemt egnet ancestor frem for blot den nærmeste. Kortets layout kan følge wrapperen, mens en anden regel reagerer på hele indholdsområdet.
main { container: main / inline-size;}
.card-wrapper { container: card / inline-size;}
@container card (width > 300px) { .card:has(img) { grid-template-columns: 1fr 3fr; }}
@container main (width < 250px) { .card img { display: none; }}container: card / inline-size er kortformen for container-name: card og container-type: inline-size. Navnet er et CSS-navn, som du selv vælger; det behøver ikke matche elementets klasse.
Øvelse 2
Gør main til en navngiven container, og giv den eksisterende card-query navnet card. Skjul derefter billedet, når main er smallere end 250px. Brug de målte bredder i previewet til at se, hvilken container hver regel følger.
Slides viser andre eksempelbredder; 300px for kortet og 250px for main er grænserne i denne øvelse.
Container query units
Container query units giver flydende værdier mellem breakpoints:
| Unit | Måling |
|---|---|
cqw / cqh |
1 % af en egnet containers bredde / højde |
cqi / cqb |
1 % af dens inline-størrelse / block-størrelse |
cqmin / cqmax |
Den mindste / største af cqi og cqb |
Enheden bruger en egnet ancestor for den relevante akse. En inline-size-container giver derfor ikke automatisk en højdereference til cqh. Uden en egnet container bruges den tilsvarende small-viewport-enhed. Se MDN om container query units.
.card-wrapper { container: card / inline-size;}
.card h2 { font-size: clamp(1.25rem, 5cqw, 2.5rem);}5cqw følger containerbredden, mens clamp() giver en nedre og øvre grænse. Query-navne bestemmer ikke i sig selv, hvilken container en unit bruger.
Øvelse 3
Gør card-overskriften flydende med cqw. Prøv først uden grænser, og tilføj derefter clamp(). Sammenlign overskriften i det brede og de smalle kort. Gennemgangen bruger andre tal end kodeeksemplet ovenfor, så du kan undersøge, hvordan faktoren påvirker skaleringen.