Zoome bilder i et rutenettoppsett PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Zoome bilder i et rutenettoppsett

Det er enkelt å lage et rutenett med bilder, takket være CSS Grid. Men å få rutenettet til å gjøre fancy ting etter bildene har blitt plassert kan være vanskelig å få av.

Si at du vil legge til en fancy sveveeffekt til bildene der de vokser og zoome utover radene og kolonnene der de sitter? Vi kan gjøre det!

Kult, ikke sant? Hvis du sjekker koden, vil du ikke finne noe JavaScript, komplekse velgere eller til og med magiske tall. Og dette er bare ett eksempel blant mange vi skal utforske!

Bygge rutenettet

HTML-koden for å lage rutenettet er like enkel som en liste over bilder i en beholder. Vi trenger ikke mer enn det.

<div class="gallery">
  <img>
  <img>
  <img>
  <!-- etc. -->
</div>

For CSS starter vi først med å sette rutenettet ved å bruke følgende:

.gallery {
  --s: 150px; /* controls the size */
  --g: 10px;  /* controls the gap */

  display: grid;
  gap: var(--g);
  width: calc(3*var(--s) + 2*var(--g)); /* 3 times the size plus 2 times the gap */
  aspect-ratio: 1;
  grid-template-columns: repeat(3, auto);
}

Kort fortalt har vi to variabler, en som styrer størrelsen på bildene og en som setter størrelsen på gapet mellom bildene. aspect-ratio bidrar til å holde ting i proporsjoner.

Du lurer kanskje på hvorfor vi bare definerer tre kolonner, men ingen rader. Nei, jeg glemte ikke radene - vi trenger bare ikke å angi dem eksplisitt. CSS Grid er i stand til å automatisk plassere elementer på implisitte rader og kolonner, noe som betyr at vi får så mange rader som nødvendig til et hvilket som helst antall bilder vi kaster på den. Vi kan eksplisitt definere radene i stedet, men vi må legge til grid-auto-flow: column for å sikre at nettleseren oppretter de nødvendige kolonnene for oss.

Her er et eksempel for å illustrere begge tilfellene. Forskjellen er at man renner i en row retning en den andre i en column retning.

Sjekk ut denne andre artikkelen jeg skrev for mer om de implisitte rutenettene og algoritmen for automatisk plassering.

Nå som vi har rutenettet vårt, er det på tide å style bildene:

.gallery > img {
  width: 0;
  height: 0;
  min-height: 100%;
  min-width: 100%;
  object-fit: cover;
}

Hover-effekten vi lager er avhengig av denne CSS. Det ser sannsynligvis rart ut for deg at vi lager bilder som både ikke har noen bredde eller høyde, men som har en minimumsbredde og -høyde på 100 %. Men du vil se at det er et ganske pent triks for det vi prøver å oppnå.

Det jeg gjør her er å fortelle nettleseren at bildene må ha 0 bredde og høyde, men må også ha en minimumshøyde lik 100%… men 100% av hva? Ved bruk av prosenter er verdien i forhold til noe annet. I dette tilfellet er bildet vårt plassert inne i en rutenettcelle og vi må vite den størrelsen for å vite hva som er 100% er i forhold til.

Nettleseren vil først ignorere min-height: 100% for å beregne størrelsen på rutenettcellene, men den vil bruke height: 0 i sin beregning. Det betyr at bildene våre ikke vil bidra til størrelsen på rutenettcellene ... fordi de teknisk sett ikke har noen fysisk størrelse. Dette vil resultere i tre like kolonner og rader som er basert på størrelsen på rutenettet (som vi definerte på .gallery's bredde og aspect-ratio). Høyden på hver rutenettcelle er ikke annet enn variabelen --s vi definerte (samme for bredden).

Zoome bilder i et rutenettoppsett

Nå som vi har dimensjonene til rutenettets celler, vil nettleseren bruke den med min-height: 100% (Og min-width: 100%) som vil tvinge bildene til å fylle hele rommet til hver rutenettcelle. Det hele kan se litt forvirrende ut, men hovedideen er å sørge for at rutenettet definerer størrelsen på bildene i stedet for omvendt. Jeg vil ikke at bildet skal definere størrelsen på rutenettet, og du vil forstå hvorfor etter å ha lagt til sveveeffekten.

Skaper sveveeffekten

Det vi trenger å gjøre er å øke skalaen til bildene når de holdes over. Vi kan gjøre det ved å justere et bilde width og height on :hover:

.gallery {
  --f: 1.5; /* controls the scale factor */
}

.gallery img:hover{
  width:  calc(var(--s) * var(--f));
  height: calc(var(--s) * var(--f));
}

Jeg la til en ny egendefinert variabel, --f, til blandingen som en skaleringsfaktor for å kontrollere størrelsen ved sveving. Legg merke til hvordan jeg multipliserer størrelsesvariabelen, --s, ved å beregne den nye bildestørrelsen.

Men du sa at bildestørrelsen må være 0. Hva skjer? Jeg har gått meg vill…

Det jeg sa er fortsatt sant, men jeg gjør et unntak for det svevende bildet. Jeg forteller nettleseren at bare ett bilde vil ha en størrelse som ikke er lik null - så det vil bidra til dimensjonen til rutenettet - mens alle de andre forblir lik 0.

Zoome bilder i et rutenettoppsett PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Zoome bilder i et rutenettoppsett

Venstre side viser rutenettet i sin naturlige tilstand uten noen pekende bilder, som er det høyre side viser. Alle rutenettcellene på venstre side er like store siden alle bildene ikke har noen fysiske dimensjoner.

På høyre side er det andre bildet i den første raden svevet, noe som gir det dimensjoner som påvirker rutenettcellens størrelse. Nettleseren vil gjøre den spesifikke rutenettcellen større ved sveving, noe som bidrar til den totale størrelsen. Og siden størrelsen på hele rutenettet er satt (fordi vi setter en fast width.gallery), vil de andre rutenettcellene logisk svare ved å bli mindre for å beholde .gallerysin totale størrelse i takt.

Det er vår zoom-effekt i aksjon! Ved å øke størrelsen på bare ett bilde påvirker vi hele rutenettkonfigurasjonen, og vi sa før at rutenettet definerer størrelsen på bildene slik at hvert bilde strekker seg inne i rutenettcellen for å fylle hele plassen.

Til dette legger vi et snev av transition Og bruk object-fit for å unngå bildeforvrengning og illusjonen er perfekt!

Jeg vet at logikken bak trikset ikke er lett å forstå. Ikke bekymre deg hvis du ikke helt forstår det. Det viktigste er å forstå strukturen til koden som brukes og hvordan du kan modifisere den for å få flere variasjoner. Det er det vi skal gjøre videre!

Legger til flere bilder

Vi laget et 3×3 rutenett for å forklare hovedtrikset, men du har sikkert gjettet at vi ikke trenger å stoppe der. Vi kan lage antall kolonner og rader til variabler og legge til så mange bilder vi vil.

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --s: 150px; /* control the size */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--s) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--s) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

Vi har to nye variabler for antall rader og kolonner. Deretter definerer vi ganske enkelt bredden og høyden på rutenettet vårt ved å bruke dem. Samme for grid-template-columns som bruker --m variabel. Og akkurat som før, trenger vi ikke eksplisitt å definere radene siden CSS Grids automatiske plasseringsfunksjon vil gjøre jobben for oss uansett hvor mange bildeelementer vi bruker.

Hvorfor ikke forskjellige verdier for bredde og høyde? Vi kan gjøre det:

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --h: 120px; /* control the height */
  --w: 150px; /* control the width */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--w) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--h) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

.gallery img:hover{
  width:  calc(var(--w)*var(--f));
  height: calc(var(--h)*var(--f));
}

Vi bytter ut --s med to variabler, en for bredden, --w, og en annen for høyden, --h. Så justerer vi alt annet deretter.

Så vi startet med et rutenett med en fast størrelse og antall elementer, men så laget vi et nytt sett med variabler for å få hvilken som helst konfigurasjon vi ønsker. Alt vi trenger å gjøre er å legge til så mange bilder vi vil og justere CSS-variablene deretter. Kombinasjonene er ubegrensede!

Hva med en fullskjermversjon? Ja, det er også mulig. Alt vi trenger er å vite hvilke verdier vi må tilordne variablene våre. Hvis vi vil N rader med bilder og vi vil at rutenettet vårt skal være fullskjerm, må vi først løse for en høyde på 100vh:

var(--n) * var(--h) + (var(--n) - 1) * var(--g) = 100vh

Samme logikk for bredden, men bruker vw istedenfor vh:

var(--m) * var(--w) + (var(--m) - 1) * var(--g) = 100vw

Vi regner for å få:

--w: (100vw - (var(--m) - 1) * var(--g)) / var(--m)
--h: (100vh - (var(--n) - 1) * var(--g)) / var(--n)

Ferdig!

Det er nøyaktig samme HTML, men med noen oppdaterte variabler som endrer rutenettets størrelse og oppførsel.

Merk at jeg har utelatt formelen vi tidligere har satt på .gallery's width og height og erstattet dem med 100vw og 100vh, henholdsvis. Formelen vil gi oss det samme resultatet, men siden vi vet hvilken verdi vi ønsker, kan vi droppe all den ekstra kompleksiteten.

Vi kan også forenkle --h og --w ved å fjerne gapet fra ligningen til fordel for dette:

--h: calc(100vh / var(--n)); /* Viewport height divided by number of rows */
--w: calc(100vw / var(--m)); /* Viewport width divided by number of columns */

Dette vil få det svevede bildet til å vokse litt mer enn det forrige eksempelet, men det er ingen stor sak siden vi kan kontrollere skalaen med --f variabelen vi bruker som en multiplikator.

Og siden variablene brukes på ett sted, kan vi fortsatt forenkle koden ved å fjerne dem helt:

Det er viktig å merke seg at denne optimaliseringen bare gjelder for fullskjermeksemplet og ikke for eksemplene vi har dekket. Dette eksemplet er et spesielt tilfelle der vi kan gjøre koden lettere ved å fjerne noe av det komplekse regnearbeidet vi trengte i de andre eksemplene.

Vi har faktisk alt vi trenger for å lage det populære mønsteret av ekspanderende paneler:

La oss grave enda dypere

La du merke til at skaleringsfaktoren vår kan være mindre enn 1? Vi kan definere størrelsen på det svevede bildet til å være mindre enn --h or --w men bildet blir større ved sveving.

Den opprinnelige rutenettets cellestørrelse er lik --w og --h, så hvorfor lager en mindre verdi rutenettcellen større? Burde ikke cellen få mindre, eller i det minste opprettholde sin opprinnelige størrelse? Og hva er den endelige størrelsen på rutenettcellen?

Vi må grave dypere inn i hvordan CSS Grid-algoritmen beregner størrelsen på rutenettcellene. Og dette innebærer å forstå CSS Grids standard strekke justering.

Her er et eksempel for å forstå logikken.

På venstre side av demoen definerte jeg en to-kolonne med auto bredde. Vi får det intuitive resultatet: to like kolonner (og to like rutenettceller). Men rutenettet satte jeg opp på høyre side av demoen, der jeg oppdaterer justeringen ved hjelp av place-content: start, ser ut til å ha ingenting.

DevTools hjelper oss med å vise oss hva som egentlig skjer i begge tilfeller:

Zoome bilder i et rutenettoppsett PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Zoome bilder i et rutenettoppsett

I det andre rutenettet har vi to kolonner, men bredden deres er lik null, så vi får to rutenettceller som er kollapset i øverste venstre hjørne av rutenettbeholderen. Dette er ikke en feil, men det logiske resultatet av rutenettets justering. Når vi dimensjonerer en kolonne (eller rad) med auto, betyr det at innholdet dikterer størrelsen - men vi har en tom div uten innhold å gi plass til.

Men siden stretch er standardjusteringen og vi har nok plass inne i rutenettet vårt, vil nettleseren strekke begge rutenettcellene likt for å dekke hele området. Det er slik rutenettet til venstre vikler seg opp med to like søyler.

Fra spesifikasjonen:

Merk at visse verdier av justify-content og align-content kan føre til at sporene blir adskilt (space-around, space-between, space-evenly) eller skal endres størrelse (stretch).

Legg merke til "skal endre størrelse" som er nøkkelen her. I det siste eksemplet brukte jeg place-content som er forkortelsen for justify-content og align-content

Og dette er begravd et sted i Grid Sizing-algoritmen spesifikasjoner:

Dette trinnet utvider spor som har en auto funksjon for maksimal sporstørrelse ved å dele eventuelle gjenværende positive, bestemt ledig plass likt blant dem. Hvis ledig plass er ubestemt, Men rutenettbeholder har en klar min bredde/høyde, bruk den størrelsen for å beregne ledig plass for dette trinnet i stedet.

«Like» forklarer hvorfor vi ender opp med like rutenettceller, men det gjelder «den ledige plassen» som er veldig viktig.

La oss ta det forrige eksemplet og legge til innhold til en av divs:

Vi la til en firkant 50px bilde. Her er en illustrasjon av hvordan hvert rutenett i vårt eksempel reagerer på det bildet:

Zoome bilder i et rutenettoppsett PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Zoome bilder i et rutenettoppsett

I det første tilfellet kan vi se at den første cellen (i rødt) er større enn den andre (i blått). I det andre tilfellet endres størrelsen på den første cellen for å passe til den fysiske størrelsen på bildet, mens den andre cellen forblir uten dimensjoner. Den ledige plassen er delt likt, men den første cellen har mer innhold inni som gjør den større.

Dette er regnestykket for å finne ut av ledig plass:

(grid width) - (gap) - (image width) = (free space)
200px - 5px - 50px = 145px 

Delt på to — antall kolonner — får vi en bredde på 72.5px for hver kolonne. Men vi legger til størrelsen på bildet, 50px, til den første kolonnen som etterlater oss med en kolonne kl 122.5px og den andre lik 72.5px.

Den samme logikken gjelder for vårt rutenett av bilder. Alle bildene har en størrelse lik 0 (ingen innhold) mens bildet som peker på, bidrar til størrelsen – selv om det er rettferdig 1px — gjør rutenettcellen større enn de andre. Av denne grunn kan skaleringsfaktoren være en hvilken som helst verdi større enn 0 selv desimaler mellom 0 og 1.

For å få den endelige bredden på rutenettcellene, gjør vi den samme beregningen for å få følgende:

(container width) - (sum of all gaps) - (hovered image width) = (free space)

Bredden på beholderen er definert av:

var(--m)*var(--w) + (var(--m) - 1)*var(--g)

…og alle hullene er lik:

(var(--m) - 1)*var(--g)

…og for bildet vi peker på har vi:

var(--w)*var(--f)

Vi kan beregne alt dette med våre variabler:

var(--m)*var(--w) - var(--w)*var(--f) = var(--w)*(var(--m) - var(--f))

Antall kolonner er definert av --m , så vi deler den ledige plassen likt for å få:

var(--w)*(var(--m) - var(--f))/var(--m)

…som gir oss størrelsen på de ikke-svevende bildene. For overvåkede bilder har vi dette:

var(--w)*(var(--m) - var(--f))/var(--m) + var(--w)*var(--f)
var(--w)*((var(--m) - var(--f))/var(--m) + var(--f))

Hvis vi ønsker å kontrollere den endelige størrelsen på det svevende bildet, vurderer vi formelen ovenfor for å få den nøyaktige størrelsen vi ønsker. Hvis vi for eksempel vil at bildet skal være dobbelt så stort:

(var(--m) - var(--f))/var(--m) + var(--f) = 2

Så verdien av skalamultiplikatoren vår, --f, må være lik:

var(--m)/(var(--m) - 1)

For tre kolonner vil vi ha 3/2 = 1.5 og det er skaleringsfaktoren jeg brukte i den første demoen av denne artikkelen fordi jeg ønsket å gjøre bildet dobbelt så stort når jeg svever!

Den samme logikken gjelder for høydeberegningen, og i tilfelle vi ønsker å kontrollere begge uavhengig av hverandre, må vi vurdere to skaleringsfaktorer for å sikre at vi har en spesifikk bredde og høyde ved sveving.

.gallery {
  /* same as before */
   --fw: 1.5; /* controls the scale factor for the width */
   --fh: 1.2; /* controls the scale factor for the height */

  /* same as before */
}

.gallery img:hover{
  width:  calc(var(--w)*var(--fw));
  height: calc(var(--h)*var(--fh));
}

Nå vet du alle hemmelighetene for å lage en hvilken som helst form for bilderutenett med en kul sveveeffekt, samtidig som du har kontroll over størrelsen du vil bruke ved å bruke matematikken vi nettopp dekket.

Innpakning opp

I min siste artikkelen, laget vi et sammensatt rutenett med noen få linjer med CSS som tok CSS Grids implisitte rutenett og funksjoner for automatisk plassering i bruk. I denne artikkelen stolte vi på noen CSS Grid-størrelseslurer for å lage et fancy rutenett med bilder som zoomer ved sveving og får rutenettet til å justere seg tilsvarende. Alt dette med en forenklet kode som er enkel å justere ved hjelp av CSS-variabler!

I neste artikkel skal vi leke med former! Vi vil kombinere CSS-rutenett med maske og utklippsbane for å få fancy rutenett av bilder.

Tidstempel:

Mer fra CSS triks