Zooma bilder i en rutnätslayout PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Zooma bilder i en rutnätslayout

Att skapa ett rutnät med bilder är enkelt tack vare CSS Grid. Men att få rutnätet att göra snygga saker efter bilderna har placerats kan vara svåra att få bort.

Säg att du vill lägga till en snygg svävningseffekt till bilderna där de växer och zooma bortom raderna och kolumnerna där de sitter? Vi kan göra det!

Coolt, eller hur? Om du kontrollerar koden hittar du inget JavaScript, komplicerade väljare eller ens magiska nummer. Och detta är bara ett exempel bland många vi kommer att utforska!

Bygga nätet

HTML-koden för att skapa rutnätet är lika enkel som en lista över bilder i en behållare. Vi behöver inte mer än så.

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

För CSS börjar vi först med att ställa in rutnätet med följande:

.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 sagt har vi två variabler, en som styr storleken på bilderna och en som anger storleken på gapet mellan bilderna. aspect-ratio hjälper till att hålla saker i proportion.

Du kanske undrar varför vi bara definierar tre kolumner men inga rader. Nej, jag glömde inte raderna – vi behöver bara inte ställa in dem explicit. CSS Grid kan automatiskt placera objekt på implicita rader och kolumner, vilket innebär att vi får så många rader som behövs till valfritt antal bilder vi kastar på den. Vi kan uttryckligen definiera raderna istället men vi måste lägga till grid-auto-flow: column för att se till att webbläsaren skapar de kolumner som behövs åt oss.

Här är ett exempel för att illustrera båda fallen. Skillnaden är att man flyter i en row riktning och den andra i en column riktning.

Checka ut den här andra artikeln jag skrev för mer om de implicita rutnäten och algoritmen för automatisk placering.

Nu när vi har vårt rutnät är det dags att styla bilderna:

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

Hover-effekten vi gör bygger på denna CSS. Det ser förmodligen konstigt ut för dig att vi gör bilder som varken har någon bredd eller höjd men som har en minsta bredd och höjd på 100 %. Men du kommer att se att det är ett ganska snyggt trick för vad vi försöker uppnå.

Vad jag gör här är att tala om för webbläsaren att bilderna måste ha 0 bredd och höjd men behöver också ha en minsta höjd lika med 100%... men 100% av vad? Vid användning av procenttal är värdet i förhållande till något annat. I det här fallet är vår bild placerad inuti en rutnätscell och vi behöver veta den storleken för att veta vad som är 100% är i förhållande till.

Webbläsaren kommer först att ignorera min-height: 100% för att beräkna storleken på rutnätscellerna, men den kommer att använda height: 0 i sin beräkning. Det betyder att våra bilder inte kommer att bidra till storleken på rutnätscellerna... eftersom de tekniskt sett inte har någon fysisk storlek. Detta kommer att resultera i tre lika stora kolumner och rader som är baserade på storleken på rutnätet (som vi definierade på .gallery's bredd och aspect-ratio). Höjden på varje rutnätscell är inget annat än variabeln --s vi definierade (samma för bredden).

Zooma bilder i en rutnätslayout

Nu när vi har dimensionerna på vårt rutnäts celler kommer webbläsaren att använda det med min-height: 100% (Och min-width: 100%) vilket kommer att tvinga bilderna att helt fylla utrymmet i varje rutnätscell. Det hela kan se lite förvirrande ut men huvudtanken är att se till att rutnätet definierar storleken på bilderna snarare än tvärtom. Jag vill inte att bilden ska definiera storleken på rutnätet och du kommer att förstå varför efter att ha lagt till hovringseffekten.

Skapar svävningseffekten

Vad vi behöver göra är att öka skalan på bilderna när de svävar. Vi kan göra det genom att justera en bild width och 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));
}

Jag lade till en ny anpassad variabel, --f, till mixen som en skalfaktor för att styra storleken vid hovring. Lägg märke till hur jag multiplicerar storleksvariabeln, --s, av den för att beräkna den nya bildstorleken.

Men du sa att bildstorleken måste vara 0. Vad är det som händer? Jag är vilse…

Det jag sa är fortfarande sant men jag gör ett undantag för den svävande bilden. Jag säger till webbläsaren att endast en bild kommer att ha en storlek som inte är lika med noll - så den kommer att bidra till dimensionen på rutnätet - medan alla andra förblir lika med 0.

Zooma bilder i en rutnätslayout PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Zooma bilder i en rutnätslayout

Den vänstra sidan visar rutnätet i dess naturliga tillstånd utan några svävande bilder, vilket är vad den högra sidan visar. Alla rutnätsceller på vänster sida är lika stora eftersom alla bilder inte har några fysiska dimensioner.

På höger sida svävar den andra bilden i första raden, vilket ger den dimensioner som påverkar rutnätscellens storlek. Webbläsaren kommer att göra den specifika rutnätscellen större vid hovring, vilket bidrar till den totala storleken. Och eftersom storleken på hela nätet är inställd (eftersom vi ställer in en fast width.gallery), kommer de andra rutnätscellerna logiskt att svara genom att bli mindre för att behålla .gallerys totala storlek i takt.

Det är vår zoomeffekt i aktion! Genom att öka storleken på endast en bild påverkar vi hela rutnätskonfigurationen, och vi sa tidigare att rutnätet definierar storleken på bilderna så att varje bild sträcker sig inuti sin rutnätscell för att fylla hela utrymmet.

Till detta lägger vi en touch av transition Och använda object-fit för att undvika bildförvrängning och illusionen är perfekt!

Jag vet att logiken bakom tricket inte är lätt att förstå. Oroa dig inte om du inte helt förstår det. Det viktigaste är att förstå strukturen på koden som används och hur man modifierar den för att få fler varianter. Det är vad vi ska göra härnäst!

Lägger till fler bilder

Vi skapade ett 3×3-rutnät för att förklara huvudtricket, men du har förmodligen gissat att vi inte skulle behöva stanna där. Vi kan göra antalet kolumner och rader variabler och lägga till så många bilder som vi vill.

.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 två nya variabler för antalet rader och kolumner. Sedan definierar vi helt enkelt bredden och höjden på vårt rutnät med hjälp av dem. Samma för grid-template-columns som använder --m variabel. Och precis som tidigare behöver vi inte explicit definiera raderna eftersom CSS Grids automatiska placeringsfunktion kommer att göra jobbet åt oss oavsett hur många bildelement vi använder.

Varför inte olika värden för bredd och höjd? Vi kan göra 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 byter ut --s med två variabler, en för bredd, --w, och en till för höjden, --h. Sedan anpassar vi allt annat därefter.

Så vi började med ett rutnät med en fast storlek och antal element, men sedan gjorde vi en ny uppsättning variabler för att få vilken konfiguration vi vill ha. Allt vi behöver göra är att lägga till så många bilder som vi vill och justera CSS-variablerna därefter. Kombinationerna är obegränsade!

Vad sägs om en helskärmsversion? Ja, det är också möjligt. Allt vi behöver är att veta vilka värden vi behöver tilldela våra variabler. Om vi ​​vill N rader av bilder och vi vill att vårt rutnät ska vara helskärm måste vi först lösa för en höjd av 100vh:

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

Samma logik för bredden, men använder vw istället för vh:

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

Vi räknar för att få:

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

Gjort!

Det är exakt samma HTML men med några uppdaterade variabler som ändrar rutnätets storlek och beteende.

Observera att jag har utelämnat formeln som vi tidigare satt på .gallery's width och height och ersatte dem med 100vw och 100vh, respektive. Formeln kommer att ge oss samma resultat, men eftersom vi vet vilket värde vi vill ha kan vi avstå från all den extra komplexiteten.

Vi kan också förenkla --h och --w genom att ta bort gapet från ekvationen till förmån för detta:

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

Detta kommer att få den svävande bilden att växa lite mer än i föregående exempel, men det är ingen stor sak eftersom vi kan styra skalan med --f variabel vi använder som en multiplikator.

Och eftersom variablerna används på ett ställe kan vi fortfarande förenkla koden genom att ta bort dem helt och hållet:

Det är viktigt att notera att denna optimering endast gäller för helskärmsexemplet och inte för exemplen vi har täckt. Det här exemplet är ett speciellt fall där vi kan göra koden lättare genom att ta bort en del av det komplexa beräkningsarbete vi behövde i de andra exemplen.

Vi har faktiskt allt vi behöver för att skapa det populära mönstret av expanderande paneler:

Låt oss gräva ännu djupare

Har du märkt att vår skalfaktor kan vara mindre än 1? Vi kan definiera storleken på den svävade bilden till att vara mindre än --h or --w men bilden blir större när du svävar.

Den initiala rutnätscellstorleken är lika med --w och --h, så varför gör ett mindre värde rutnätscellen större? Borde inte cellen få mindre, eller åtminstone behålla sin ursprungliga storlek? Och vad är den slutliga storleken på rutnätscellen?

Vi måste gräva djupare i hur CSS Grid-algoritmen beräknar storleken på rutnätscellerna. Och detta handlar om att förstå CSS Grids standard sträckinriktning.

Här är ett exempel för att förstå logiken.

På vänster sida av demot definierade jag en två-kolumn med auto bredd. Vi får det intuitiva resultatet: två lika stora kolumner (och två lika stora rutnätsceller). Men rutnätet satte jag upp på höger sida av demon, där jag uppdaterar justeringen med hjälp av place-content: start, verkar ha ingenting.

DevTools hjälper till att visa oss vad som verkligen händer i båda fallen:

Zooma bilder i en rutnätslayout PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Zooma bilder i en rutnätslayout

I det andra rutnätet har vi två kolumner, men deras bredd är lika med noll, så vi får två rutnätsceller som är kollapsade i det övre vänstra hörnet av rutnätsbehållaren. Detta är inte en bugg men det logiska resultatet av rutnätets justering. När vi storleksanpassar en kolumn (eller rad) med auto, betyder det att dess innehåll dikterar dess storlek — men vi har en tom div utan innehåll att ge plats för.

Men eftersom stretch är standardinställningen och vi har tillräckligt med utrymme i vårt rutnät, kommer webbläsaren att sträcka ut båda rutnätscellerna lika för att täcka hela området. Det är så rutnätet till vänster vindar upp med två lika stora kolumner.

Från specifikationen:

Observera att vissa värden på justify-content och align-content kan göra att spåren är åtskilda (space-around, space-between, space-evenly) eller ska ändras storlek (stretch).

Notera "som ska ändras storlek" som är nyckeln här. I det sista exemplet använde jag place-content som är förkortningen för justify-content och align-content

Och det här är begravt någonstans i algoritmen Grid Sizing specifikationer:

Detta steg utökar spår som har en bil max spårstorleksfunktion genom att dividera eventuella kvarvarande positiva, bestämd fritt utrymme lika bland dem. Om det lediga utrymmet är obestämd, Men den gallerbehållare har en bestämd min bredd/höjd, använd den storleken för att beräkna ledigt utrymme för det här steget istället.

"Lika" förklarar varför vi slutar med lika stora rutnätsceller, men det gäller "det fria utrymmet" vilket är mycket viktigt.

Låt oss ta det föregående exemplet och lägga till innehåll till en av de divs:

Vi lade till en kvadrat 50px bild. Här är en illustration av hur varje rutnät i vårt exempel reagerar på den bilden:

Zooma bilder i en rutnätslayout PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Zooma bilder i en rutnätslayout

I det första fallet kan vi se att den första cellen (i rött) är större än den andra (i blått). I det andra fallet ändras storleken på den första cellen för att passa bildens fysiska storlek medan den andra cellen förblir utan dimensioner. Det lediga utrymmet är lika uppdelat, men den första cellen har mer innehåll inuti vilket gör den större.

Detta är matematiken för att ta reda på vårt lediga utrymme:

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

Delat med två — antalet kolumner — får vi en bredd på 72.5px för varje kolumn. Men vi lägger till storleken på bilden, 50px, till den första kolumnen som lämnar oss med en kolumn vid 122.5px och den andra lika med 72.5px.

Samma logik gäller för vårt rutnät av bilder. Alla bilder har en storlek lika med 0 (inget innehåll) medan den svävade bilden bidrar till storleken – även om det är bara 1px — gör dess rutnätscell större än de andra. Av denna anledning kan skalfaktorn vara vilket värde som helst större än 0 även decimaler mellan 0 och 1.

För att få den slutliga bredden på rutnätscellerna gör vi samma beräkning för att få följande:

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

Behållarens bredd definieras av:

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

…och alla luckor är lika med:

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

...och för den svävande bilden har vi:

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

Vi kan beräkna allt detta med våra variabler:

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

Antalet kolumner definieras av --m , så vi delar det lediga utrymmet lika för att få:

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

...vilket ger oss storleken på de bilder som inte svävar. För svävade bilder har vi detta:

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

Om vi ​​vill kontrollera den slutliga storleken på den svävade bilden, överväger vi formeln ovan för att få den exakta storleken vi vill ha. Om vi ​​till exempel vill att bilden ska vara dubbelt så stor:

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

Så, värdet av vår skalmultiplikator, --f, måste vara lika med:

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

För tre kolumner kommer vi att ha 3/2 = 1.5 och det är skalfaktorn jag använde i den första demon av den här artikeln eftersom jag ville göra bilden dubbelt så stor när jag svävar!

Samma logik gäller för höjdberäkningen och om vi vill styra båda oberoende av varandra måste vi överväga två skalfaktorer för att säkerställa att vi har en specifik bredd och höjd vid hovring.

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

Nu vet du alla hemligheterna för att skapa vilken typ av bildrutnät som helst med en cool svävningseffekt samtidigt som du har kontroll över storleken du vill använda med hjälp av matematiken vi just täckte.

Inslagning upp

I min sista artikel, skapade vi ett komplext utseende rutnät med några rader CSS som använde CSS Grids implicita rutnät och funktioner för automatisk placering. I den här artikeln förlitade vi oss på lite CSS-rutnätsstorlekstrick för att skapa ett snyggt rutnät av bilder som zoomar vid svävning och gör att rutnätet justeras därefter. Allt detta med en förenklad kod som är lätt att justera med hjälp av CSS-variabler!

I nästa artikel kommer vi att leka med former! Vi kommer att kombinera CSS-rutnät med mask och klippbana för att få snygga rutnät av bilder.

Tidsstämpel:

Mer från CSS-tricks