CSS Container Queries øker fortsatt, og mange av oss får hendene våte med dem, selv om det er for små eksperimenter eller noe. De er flotte, men ikke helt fulle, nettleserstøtte — nok til å rettferdiggjøre å bruke dem i noen prosjekter, men kanskje ikke i den grad at vi kan bli fristet til å begynne å erstatte mediespørsmål fra tidligere prosjekter med skinnende nye forespørsler om beholderstørrelse.
Men de er sikkert nyttige! Faktisk har jeg allerede vært borti noen få situasjoner der jeg virkelig ønsket å strekke meg etter dem, men bare ikke klarte å overkomme støttekravene. Hvis jeg hadde kunnet bruke dem, er det slik det hadde sett ut i de situasjonene.
Alle de følgende demoene vil best sees i Chrome eller Safari når dette skrives. Firefox planlegger å skipsstøtte i versjon 109.
Tilfelle 1: Kortnett
Du måtte liksom forvente denne, ikke sant? Det er et så vanlig mønster at vi alle ser ut til å støte på det på et tidspunkt. Men faktum er at beholderstørrelsespørringer ville ha vært en stor tidsbesparelse for meg med et bedre resultat hvis jeg hadde vært i stand til å bruke dem over standard mediespørringer.
La oss si at du har fått i oppgave å bygge dette kortrutenettet med kravet om at hvert kort skal ha sideforholdet 1:1:
Det er tøffere enn det ser ut! Problemet er at størrelsen på en komponents innhold etter visningsportens bredde overlater deg til nåde for hvordan komponenten reagerer på visningsporten – i tillegg til måten andre forfedrebeholdere reagerer på den. Hvis du for eksempel vil at skriftstørrelsen til en kortoverskrift skal reduseres når kortet treffer en viss innebygd størrelse, er det ingen pålitelig måte å gjøre det på.
Du kan stille inn skriftstørrelsen vw
enheter, antar jeg, men komponenten er fortsatt knyttet til nettleserens visningsportbredde. Og det kan skape problemer når kortnettet brukes andre i sammenhenger som kanskje ikke har de samme bruddpunktene.
I mitt virkelige prosjekt landet jeg på en JavaScript-tilnærming som ville:
- Lytt etter en hendelse som endrer størrelse.
- Beregn bredden på hvert kort.
- Legg til en innebygd skriftstørrelse på hvert kort basert på dets bredde.
- Style alt inne ved å bruke
em
enheter.
Virker som mye arbeid, ikke sant? Men det er en stabil løsning for å få den nødvendige skaleringen på tvers av ulike skjermstørrelser i ulike sammenhenger.
Containerforespørsler ville vært så mye bedre fordi de gir oss containerspørringsenheter, slik som cqw
enhet. Du har sikkert allerede fått det, men 1cqw
er lik 1%
av en containers bredde. Vi har også cqi
enhet som er et mål på en containers innebygde bredde, og cqb
for en containers blokkbredde. Så hvis vi har en kortbeholder altså 500px
bred, a 50cqw
verdi beregnes til 250px
.
Hvis jeg hadde vært i stand til å bruke containerspørringer i kortnettet mitt, kunne jeg ha satt opp .card
komponent som en beholder:
.card {
container: card / size;
}
Da kunne jeg ha satt en inneromslag med padding
som skalerer kl 10%
av .card
's bredde ved å bruke cqw
enhet:
.card__inner {
padding: 10cqw;
}
Det er en fin måte å skalere avstanden mellom kortets kanter og innholdet konsekvent uansett hvor kortet brukes ved en gitt visningsportbredde. Ingen medieforespørsler kreves!
En annen idé? Bruk cqw
enheter for skriftstørrelsen til det indre innholdet, og bruk deretter utfylling em
enheter:
.card__inner {
font-size: 5cqw;
padding: 2em;
}
5cqw
er en vilkårlig verdi - bare en som jeg slo meg til ro med. Den polstringen er fortsatt lik 10cqw
siden em
enhet er i forhold til .card__inner
skriftstørrelse!
Fikk du med deg det? De 2em
er i forhold til 5cqw
skriftstørrelse som er angitt på samme beholder. Containere fungerer annerledes enn det vi er vant til, som em
enheter er i forhold til det samme elementet font-size value
. Men det jeg raskt la merke til er at containerspørringsenheter forholder seg til nærmeste forelder som også er en container.
For eksempel, 5cqw
skaleres ikke basert på .card
elementets bredde i dette eksemplet:
.card {
container: card / size;
container-name: card;
font-size: 5cqw;
}
Snarere skalerer den til den nærmeste forelderen som er definert som en beholder. Det er derfor jeg satte opp en .card__inner
innpakning.
Case 2: Vekslende layout
Jeg trengte enda en kortkomponent i et annet prosjekt. Denne gangen trengte jeg kortet for å gå over fra et landskapsoppsett til et portrettoppsett... så tilbake til landskapet, og tilbake til portrett igjen når skjermen blir mindre.
Jeg gjorde det skitne arbeidet med å få denne komponenten til å gå til portrett ved de to spesifikke visningsområdene (rop ut til ny syntaks for mediesøkeområde!), men igjen, problemet er at den deretter låses til mediespørringene som er satt på den, dens overordnede og alt annet som kan svare på visningsportens bredde. Vi vil ha noe som fungerer i alle tilstander uten å bekymre oss for å lure på hvor innholdet skal bryte!
Containerforespørsler ville ha gjort dette til en lek, takket være @container
regel:
.info-card {
container-type: inline-size;
container-name: info-card;
}
@container info-card (max-width: 500px) {
.info-card__inner {
flex-direction: column;
}
}
Ett søk, uendelig flyt:
Men hold ut! Det er noe du kanskje vil passe på. Spesifikt kan det være vanskelig å bruke en beholderspørring som dette innenfor et rekvisittbasert designsystem. For eksempel dette .info-card
komponent kan inneholde underordnede komponenter som er avhengige av rekvisitter for å endre utseendet.
Hvorfor er det en stor sak? Kortets stående layout kan kreve den alternative stilen, men du kan ikke endre JavaScript-rekvisitter med CSS. Som sådan risikerer du å duplisere de nødvendige stilene. Jeg var faktisk inne på dette og hvordan du kan omgå det i en annen artikkel. Hvis du trenger å bruke beholderspørringer for en betydelig del av stylingen din, må du kanskje basere hele designsystemet rundt dem i stedet for å prøve å sette dem inn i et eksisterende designsystem som er tungt på medieforespørsler.
Tilfelle 3: SVG-strøk
Her er et annet supervanlig mønster jeg nylig har brukt der spørsmål om beholderstørrelse ville ha resultert i et mer polert produkt. La oss si at du har et ikon låst med en overskrift:
Heading
Det er ganske enkelt å skalere ikonet med tittelens størrelse, selv uten medieforespørsler. Problemet er imidlertid at SVG-ene stroke-width
kan bli for tynn til å bli lagt merke til så godt i en mindre størrelse, og kanskje fange for mye oppmerksomhet med et supertykt slag i en større størrelse.
Jeg har måttet opprette og bruke klasser på hver ikonforekomst for å bestemme størrelsen og strekbredden. Det er greit hvis ikonet er ved siden av en overskrift som er stilt med en fast skriftstørrelse, antar jeg, men det er ikke så bra når du arbeider med flytende type som stadig endres.
Overskriftens skriftstørrelse kan være basert på visningsportens bredde, så SVG-ikonet må justeres tilsvarende hvor streken fungerer uansett størrelse. Du kan gjøre strekbredden i forhold til overskriftens font-size
ved å sette den inn em
enheter. Men hvis du har et spesifikt sett med slagstørrelser som du må holde deg til, ville ikke dette fungere fordi det ellers skaleres lineært - det er ingen måte å justere det til en bestemt stroke-width
verdi på visse punkter uten å ty til mediespørringer på visningsportens bredde.
Men her er hva jeg ville ha gjort hvis jeg hadde hatt luksusen av containerspørringer på den tiden:
.icon {
container: icon / size;
width: 1em;
height: 1em;
}
.icon svg {
width: 100%;
height: 100%;
fill: none;
stroke: #ccc;
stroke-width: 0.8;
}
@container icon (max-width: 70px) {
.icon svg {
stroke-width: 1.5;
}
}
@container icon (max-width: 35px) {
.icon svg {
stroke-width: 3;
}
}
Sammenlign implementeringene og se hvordan containerspørringsversjonen fester SVG-streken til de spesifikke breddene jeg ønsker basert på containerens bredde.
Bonus: Andre typer forespørsler om beholderstørrelse
OK, så jeg har faktisk ikke vært borti dette på et ekte prosjekt. Men mens jeg kjemmet gjennom informasjon om containerspørringer, la jeg merke til at det er flere ting vi kan spørre på en container som er relatert til containerens størrelse eller fysiske dimensjoner.
De fleste eksemplene jeg har sett spør etter width
, max-width
og min-width
, height
, block-size
og inline-size
som jeg har gjort gjennom denne artikkelen.
@container info-card (max-width: 500px) {
.info-card__inner {
flex-direction: column;
}
}
Men MDN skisserer ytterligere to ting vi kan spørre mot. En er orientation
noe som gir perfekt mening fordi vi bruker det hele tiden i mediesøk. Det er ikke annerledes med beholdersøk:
@media screen (orientation: landscape) {
.info-card__inner {
/* Style away! */
}
}
@container info-card (orientation: landscape) {
.info-card__inner {
/* Style away! */
}
}
Den andre? Det er aspect-ratio
, tro det eller ei:
@container info-card (aspect-ratio: 3/2) {
.info-card__inner {
/* Style away! */
}
}
Her er en redigerbar demo for å leke med begge eksemplene:
Jeg har egentlig ikke funnet et godt bruksområde for noen av disse ennå. Hvis du har noen ideer eller føler at det kunne ha hjulpet deg i prosjektene dine, gi meg beskjed i kommentarfeltet!