Zephyrnet-logo

Afbeeldingen zoomen in een rasterlay-out

Datum:

Het maken van een raster met afbeeldingen is eenvoudig dankzij CSS Grid. Maar het raster mooie dingen laten doen na de afbeeldingen zijn geplaatst kan lastig zijn om te trekken.

Stel dat je een mooi zweefeffect wilt toevoegen aan de afbeeldingen waar ze groeien en zoomen buiten de rijen en kolommen waar ze zitten? We kunnen dat doen!

Cool toch? Als u de code controleert, vindt u geen JavaScript, complexe selectors of zelfs magische getallen. En dit is slechts een van de vele voorbeelden die we zullen onderzoeken!

Het raster bouwen

De HTML-code om het raster te maken is net zo eenvoudig als een lijst met afbeeldingen in een container. Meer hebben we niet nodig.

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

Voor de CSS beginnen we eerst met het instellen van het raster met behulp van het volgende:

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

Kortom, we hebben twee variabelen, één die de grootte van de afbeeldingen bepaalt en één die de grootte van de opening tussen afbeeldingen bepaalt. aspect-ratio helpt om de zaken in verhouding te houden.

U vraagt ​​zich misschien af ​​waarom we slechts drie kolommen definiëren, maar geen rijen. Nee, ik ben de rijen niet vergeten - we hoeven ze alleen niet expliciet in te stellen. CSS Grid kan automatisch items op impliciete rijen en kolommen, wat betekent dat we zoveel rijen krijgen als nodig zijn voor een willekeurig aantal afbeeldingen dat we erop gooien. We kunnen in plaats daarvan de rijen expliciet definiëren, maar we moeten toevoegen grid-auto-flow: column om ervoor te zorgen dat de browser de benodigde kolommen voor ons maakt.

Hier is een voorbeeld om beide gevallen te illustreren. Het verschil is dat men in een row richting en de andere in a column richting.

Check out dit andere artikel dat ik schreef voor meer informatie over de impliciete rasters en het algoritme voor automatische plaatsing.

Nu we ons raster hebben, is het tijd om de afbeeldingen te stylen:

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

Het zweefeffect dat we maken, is afhankelijk van deze CSS. Het ziet er waarschijnlijk raar uit dat we afbeeldingen maken die zowel geen breedte als hoogte hebben, maar een minimale breedte en hoogte van 100% hebben. Maar je zult zien dat het een mooie truc is voor wat we proberen te bereiken.

Wat ik hier doe, is de browser vertellen dat de afbeeldingen moeten hebben 0 breedte en hoogte, maar moet ook een minimale hoogte hebben die gelijk is aan 100%… maar 100% van wat? Bij gebruik van percentages is de waarde ten opzichte van iets anders. In dit geval wordt onze afbeelding in a . geplaatst rastercel en we moeten die maat weten om te weten wat het is 100% is ten opzichte van.

De browser negeert eerst min-height: 100% om de grootte van de rastercellen te berekenen, maar het gebruikt de height: 0 in zijn berekening. Dat betekent dat onze afbeeldingen niet bijdragen aan de grootte van de rastercellen ... omdat ze technisch gezien geen fysieke grootte hebben. Dit resulteert in drie gelijke kolommen en rijen die zijn gebaseerd op de grootte van het raster (die we hebben gedefinieerd op de .gallery's breedte en aspect-ratio). De hoogte van elke rastercel is niets anders dan de variabele --s we hebben gedefinieerd (hetzelfde voor de breedte).

Nu we de afmetingen van de cellen van ons raster hebben, zal de browser het gebruiken met min-height: 100% (En min-width: 100%) waardoor de afbeeldingen de ruimte van elke rastercel volledig zullen vullen. Het geheel ziet er misschien wat verwarrend uit, maar het belangrijkste idee is om ervoor te zorgen dat het raster de grootte van de afbeeldingen bepaalt in plaats van andersom. Ik wil niet dat de afbeelding de grootte van het raster definieert en u zult begrijpen waarom na het toevoegen van het zweefeffect.

Het zweefeffect creëren

Wat we moeten doen is de schaal van de afbeeldingen vergroten wanneer ze zweven. Dat kunnen we doen door een afbeelding aan te passen width en 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));
}

Ik heb een nieuwe aangepaste variabele toegevoegd, --f, naar de mix als schaalfactor om de grootte bij zweven te regelen. Merk op hoe ik de variabele grootte vermenigvuldig, --s, door het om de nieuwe afbeeldingsgrootte te berekenen.

Maar je zei dat de afbeeldingsgrootte 0 moet zijn. Wat is er aan de hand? Ik ben verdwaald…

Wat ik zei is nog steeds waar, maar ik maak een uitzondering voor de zwevende afbeelding. Ik vertel de browser dat slechts één afbeelding een grootte heeft die niet gelijk is aan nul - dus het zal bijdragen aan de afmeting van het raster - terwijl alle andere gelijk blijven aan 0.

De linkerkant toont het raster in zijn natuurlijke staat zonder zwevende afbeeldingen, wat de rechterkant laat zien. Alle rastercellen aan de linkerkant zijn even groot omdat alle afbeeldingen geen fysieke afmetingen hebben.

Aan de rechterkant zweeft de tweede afbeelding in de eerste rij, waardoor deze afmetingen krijgt die van invloed zijn op de grootte van de rastercel. De browser maakt die specifieke rastercel groter bij zweven, wat bijdraagt ​​aan de totale grootte. En aangezien de grootte van het hele raster is ingesteld (omdat we een vaste width op de .gallery), zullen de andere rastercellen logischerwijs reageren door kleiner te worden om de .gallery's totale grootte in tact.

Dat is ons zoomeffect in actie! Door de grootte van slechts één afbeelding te vergroten, beïnvloeden we de hele rasterconfiguratie, en we zeiden eerder dat het raster de grootte van de afbeeldingen definieert, zodat elke afbeelding zich uitstrekt in zijn rastercel om alle ruimte te vullen.

Hier voegen we een vleugje aan toe transition en gebruiken object-fit om beeldvervorming te voorkomen en de illusie is perfect!

Ik weet dat de logica achter de truc niet gemakkelijk te begrijpen is. Maak je geen zorgen als je het niet helemaal begrijpt. Het belangrijkste is om de structuur van de gebruikte code te begrijpen en hoe deze te wijzigen om meer variaties te krijgen. Dat is wat we hierna gaan doen!

Meer afbeeldingen toevoegen

We hebben een raster van 3×3 gemaakt om de belangrijkste truc uit te leggen, maar je hebt waarschijnlijk al geraden dat we daar niet hoeven te stoppen. We kunnen het aantal kolommen en rijen variabelen maken en zoveel afbeeldingen toevoegen als we willen.

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

We hebben twee nieuwe variabelen voor het aantal rijen en kolommen. Vervolgens definiëren we eenvoudig de breedte en hoogte van ons raster met behulp van hen. Hetzelfde geldt voor grid-template-columns welke de --m variabel. En net als voorheen hoeven we de rijen niet expliciet te definiëren, omdat de automatische plaatsingsfunctie van het CSS Grid het werk voor ons zal doen, ongeacht hoeveel afbeeldingselementen we gebruiken.

Waarom geen verschillende waarden voor de breedte en hoogte? We kunnen dat doen:

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

wij vervangen --s met twee variabelen, één voor de breedte, --w, en nog een voor de hoogte, --h. Dan passen we al het andere daarop aan.

We zijn dus begonnen met een raster met een vaste grootte en een vast aantal elementen, maar daarna hebben we een nieuwe set variabelen gemaakt om elke gewenste configuratie te krijgen. We hoeven alleen maar zoveel afbeeldingen toe te voegen als we willen en de CSS-variabelen dienovereenkomstig aan te passen. De combinaties zijn eindeloos!

Hoe zit het met een versie op volledig scherm? Ja, dat kan ook. Het enige dat we nodig hebben, is te weten welke waarden we aan onze variabelen moeten toewijzen. Als we willen N rijen afbeeldingen en we willen dat ons raster volledig scherm is, moeten we eerst oplossen voor een hoogte van 100vh:

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

Dezelfde logica voor de breedte, maar met behulp van vw in plaats van vh:

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

We doen de wiskunde om te krijgen:

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

Klaar!

Het is exact dezelfde HTML, maar met enkele bijgewerkte variabelen die de grootte en het gedrag van het raster veranderen.

Merk op dat ik de formule heb weggelaten die we eerder hadden ingesteld op de .gallery's width en height en verving ze door 100vw en 100vh, respectievelijk. De formule geeft ons hetzelfde resultaat, maar omdat we weten welke waarde we willen, kunnen we al die toegevoegde complexiteit weggooien.

We kunnen ook de vereenvoudigen --h en --w door de kloof uit de vergelijking te verwijderen in het voordeel hiervan:

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

Hierdoor zal de zwevende afbeelding iets meer groeien dan in het vorige voorbeeld, maar het is niet erg omdat we de schaal kunnen regelen met de --f variabele die we gebruiken als vermenigvuldiger.

En aangezien de variabelen op één plaats worden gebruikt, kunnen we de code nog steeds vereenvoudigen door ze helemaal te verwijderen:

Het is belangrijk op te merken dat deze optimalisatie alleen van toepassing is op het voorbeeld op volledig scherm en niet op de voorbeelden die we hebben behandeld. Dit voorbeeld is een specifiek geval waarin we de code lichter kunnen maken door een deel van het complexe rekenwerk te verwijderen dat we in de andere voorbeelden nodig hadden.

We hebben eigenlijk alles wat we nodig hebben om het populaire patroon van uitzettende panelen te creëren:

Laten we nog dieper graven

Is het je opgevallen dat onze schaalfactor kleiner kan zijn dan 1? We kunnen de grootte van de zwevende afbeelding definiëren om kleiner te zijn dan --h or --w maar de afbeelding wordt groter bij de muisaanwijzer.

De initiële celgrootte van het raster is gelijk aan --w en --h, dus waarom maken kleinere waarden de rastercel? groter? Zou de cel niet moeten kleinere, of in ieder geval de oorspronkelijke grootte behouden? En wat is de uiteindelijke grootte van de rastercel?

We moeten dieper ingaan op hoe het CSS Grid-algoritme de grootte van de rastercellen berekent. En dit omvat het begrijpen van de standaard van CSS Grid uitlijning uitrekken.

Hier is een voorbeeld om de logica te begrijpen.

Aan de linkerkant van de demo definieerde ik een tweekoloms met auto breedte. We krijgen het intuïtieve resultaat: twee gelijke kolommen (en twee gelijke rastercellen). Maar het raster dat ik aan de rechterkant van de demo heb ingesteld, waar ik de uitlijning bijwerk met place-content: start, lijkt niets te hebben.

DevTools helpt ons te laten zien wat er echt gebeurt in beide gevallen:

In het tweede raster hebben we twee kolommen, maar hun breedte is gelijk aan nul, dus we krijgen twee rastercellen die zijn samengevouwen in de linkerbovenhoek van de rastercontainer. Dit is niet een bug maar het logische resultaat van de uitlijning van het raster. Wanneer we de grootte van een kolom (of rij) met auto, het betekent dat de inhoud de grootte bepaalt - maar we hebben een lege div zonder inhoud om ruimte voor te maken.

Maar sinds stretch is de standaarduitlijning en we hebben voldoende ruimte in ons raster, de browser zal beide rastercellen gelijkmatig uitrekken om dat hele gebied te bestrijken. Zo eindigt het raster aan de linkerkant met twee gelijke kolommen.

Van de specificatie:

Merk op dat bepaalde waarden van justify-content en align-content kan ervoor zorgen dat de tracks uit elkaar staan ​​(space-around, space-between, space-evenly) of te verkleinen (stretch).

Let op de "om het formaat te wijzigen", wat hier de sleutel is. In het laatste voorbeeld gebruikte ik place-content wat is de afkorting voor justify-content en align-content

En dit is ergens begraven in het Grid Sizing-algoritme specs:

Deze stap breidt tracks uit met een auto max track sizing functie door eventuele resterende positieve te delen, definitief vrije ruimte gelijk onder hen. Als de vrije ruimte is onbepaald, Maar de rastercontainer heeft een duidelijke min-breedte/hoogte, gebruik in plaats daarvan die grootte om de vrije ruimte voor deze stap te berekenen.

"Equally" verklaart waarom we eindigen met gelijke rastercellen, maar het is van toepassing op "de vrije ruimte", wat erg belangrijk is.

Laten we het vorige voorbeeld nemen en inhoud toevoegen aan een van de divs:

We hebben een vierkant toegevoegd 50px afbeelding. Hier is een illustratie van hoe elk raster in ons voorbeeld op die afbeelding reageert:

In het eerste geval kunnen we zien dat de eerste cel (in rood) groter is dan de tweede (in blauw). In het tweede geval verandert de grootte van de eerste cel om te passen bij de fysieke grootte van de afbeelding, terwijl de tweede cel geen afmetingen heeft. De vrije ruimte is gelijk verdeeld, maar de eerste cel heeft meer inhoud waardoor deze groter wordt.

Dit is de wiskunde om onze vrije ruimte te berekenen:

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

Gedeeld door twee - het aantal kolommen - krijgen we een breedte van 72.5px voor elke kolom. Maar we voegen de grootte van de afbeelding toe, 50px, naar de eerste kolom die ons verlaat met één kolom op 122.5px en de tweede gelijk aan 72.5px.

Dezelfde logica is van toepassing op ons raster van afbeeldingen. Alle afbeeldingen hebben een grootte gelijk aan: 0 (geen inhoud) terwijl de zwevende afbeelding bijdraagt ​​aan de grootte — ook al is het maar 1px — de rastercel groter maken dan de andere. Om deze reden kan de schaalfactor elke waarde groter zijn dan 0 zelfs decimalen tussen 0 en 1.

Om de uiteindelijke breedte van de rastercellen te krijgen, doen we dezelfde berekening om het volgende te krijgen:

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

De breedte van de container wordt bepaald door:

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

... en alle hiaten zijn gelijk aan:

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

... en voor de zwevende afbeelding hebben we:

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

Dat kunnen we allemaal uitrekenen met onze variabelen:

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

Het aantal kolommen wordt bepaald door --m , dus we verdelen die vrije ruimte gelijk om te krijgen:

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

... wat ons de grootte geeft van de niet-zwevende afbeeldingen. Voor zwevende afbeeldingen hebben we dit:

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

Als we de uiteindelijke grootte van de zwevende afbeelding willen bepalen, overwegen we de bovenstaande formule om de exacte grootte te krijgen die we willen. Als we bijvoorbeeld willen dat de afbeelding twee keer zo groot is:

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

Dus de waarde van onze schaalvermenigvuldiger, --f, moet gelijk zijn aan:

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

Voor drie kolommen hebben we 3/2 = 1.5 en dat is de schaalfactor die ik in de eerste demo van dit artikel heb gebruikt, omdat ik de afbeelding twee keer zo groot wilde maken bij het zweven!

Dezelfde logica is van toepassing op de hoogteberekening en als we ze allebei onafhankelijk willen besturen, moeten we twee schaalfactoren in overweging nemen om ervoor te zorgen dat we een specifieke breedte en hoogte hebben bij het zweven.

.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 ken je alle geheimen om elk soort afbeeldingsraster te maken met een cool zweefeffect, terwijl je ook controle hebt over de grootte die je wilt met behulp van de wiskunde die we zojuist hebben behandeld.

Afsluiten

Naar mijn laatste artikel, hebben we een complex ogend raster gemaakt met een paar regels CSS waarmee het impliciete raster en de automatische plaatsingsfuncties van CSS Grid kunnen worden gebruikt. In dit artikel vertrouwden we op wat trucjes voor het bepalen van de CSS-rasteromvang om een ​​fraai raster van afbeeldingen te maken die bij het zweven inzoomen en ervoor zorgen dat het raster zich dienovereenkomstig aanpast. Dit alles met een vereenvoudigde code die eenvoudig aan te passen is met behulp van CSS-variabelen!

In het volgende artikel gaan we spelen met vormen! We zullen CSS-raster combineren met masker en clippad om een ​​mooi raster van afbeeldingen te krijgen.

spot_img

Laatste intelligentie

spot_img

Chat met ons

Hallo daar! Hoe kan ik u helpen?