V redu, torej zadnjič, ko smo se prijavili, smo uporabljali CSS Grid in jih kombinirali s CSS clip-path
in mask
tehnike za ustvarjanje mrež z domiselnimi oblikami.
Tukaj je samo ena od fantastičnih mrež, ki smo jih naredili skupaj:
Ste pripravljeni na drugi krog? Še vedno delamo s CSS Grid, clip-path
in mask
, vendar bomo do konca tega članka našli različne načine za razporeditev slik na mreži, vključno z nekaterimi učinki lebdenja, ki omogočajo pristno, interaktivno izkušnjo ogledovanja slik.
In ugani kaj? Uporabljamo isto oznako, kot smo jo uporabili zadnjič. Evo še enkrat:
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<!-- as many times as we want -->
</div>
Tako kot prejšnji članek potrebujemo samo posodo s slikami v njej. Nič več!
Mreža ugnezdene slike
Zadnjič so bile naše mreže, no, tipične slikovne mreže. Razen čednih oblik, s katerimi smo jih zamaskirali, so bile precej standardne simetrične mreže, kar zadeva, kako smo slike postavili v notranjost.
Poskusimo ugnezditi sliko na sredino mreže:
Začnemo z nastavitvijo mreže 2✕2 za štiri slike:
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gap between images */
display: grid;
gap: var(--g);
grid-template-columns: repeat(2, auto);
}
.gallery > img {
width: var(--s);
aspect-ratio: 1;
object-fit: cover;
}
Nič zapletenega še. Naslednji korak je, da odrežemo vogal naših slik, da ustvarimo prostor za ugnezdeno sliko. Imam že podroben članek o kako rezati vogale z uporabo clip-path
in mask
. Lahko uporabite tudi mojo spletni generator da dobite CSS za maskiranje vogalov.
Tukaj moramo izrezati vogale pod kotom, ki je enak 90deg
. Lahko uporabimo enako tehnika koničnega gradienta iz tega članka, da to storite:
.gallery > img {
mask: conic-gradient(from var(--_a), #0000 90deg, #000 0);
}
.gallery > img:nth-child(1) { --_a: 90deg; }
.gallery > img:nth-child(2) { --_a: 180deg; }
.gallery > img:nth-child(3) { --_a: 0deg; }
.gallery > img:nth-child(4) { --_a:-90deg; }
Lahko bi uporabili clip-path
metoda za rezanje vogalov iz istega članka, vendar je maskiranje s prelivi bolj primerno tukaj, ker imamo enako konfiguracijo za vse slike - vse, kar potrebujemo, je rotacija (definirana s spremenljivko --_a
) dosežemo učinek, tako da maskiramo od znotraj namesto od zunanjih robov.
Zdaj lahko ugnezdeno sliko postavimo v maskiran prostor. Najprej poskrbimo, da imamo v HTML peti slikovni element:
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
</div>
Zanašali se bomo na dobro staro absolutno pozicioniranje, da ga bomo uvrstili tja:
.gallery > img:nth-child(5) {
position: absolute;
inset: calc(50% - .5*var(--s));
clip-path: inset(calc(var(--g) / 4));
}
O inset
Lastnost nam omogoča, da sliko postavimo na sredino z eno samo deklaracijo. Poznamo velikost slike (definirano s spremenljivko --s
), in vemo, da je velikost vsebnika enaka 100 %. Naredimo nekaj matematike in razdalja od vsakega roba mora biti enaka (100% - var(--s))/2
.
Morda se sprašujete, zakaj uporabljamo clip-path
sploh tukaj. Uporabljamo ga z ugnezdeno sliko, da imamo dosledno vrzel. Če bi ga odstranili, bi opazili, da nimamo enake vrzeli med vsemi slikami. Na ta način malo odrežemo peto sliko, da dobimo ustrezen razmik okoli nje.
Ponovno celotna koda:
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gap between images */
display: grid;
gap: var(--g);
grid-template-columns: repeat(2, auto);
position: relative;
}
.gallery > img {
width: var(--s);
aspect-ratio: 1;
object-fit: cover;
mask: conic-gradient(from var(--_a), #0000 90deg, #000 0);
}
.gallery > img:nth-child(1) {--_a: 90deg}
.gallery > img:nth-child(2) {--_a:180deg}
.gallery > img:nth-child(3) {--_a: 0deg}
.gallery > img:nth-child(4) {--_a:-90deg}
.gallery > img:nth-child(5) {
position: absolute;
inset: calc(50% - .5*var(--s));
clip-path: inset(calc(var(--g) / 4));
}
Zdaj se mnogi od vas morda tudi sprašujete: zakaj vse te zapletene stvari, ko lahko zadnjo sliko postavimo na vrh in ji dodamo obrobo? To bi skrilo slike pod ugnezdeno sliko brez maske, kajne?
To je res in dobili bomo naslednje:
Ne mask
, ne clip-path
. Da, kodo je enostavno razumeti, vendar obstaja majhna pomanjkljivost: barva obrobe mora biti enaka barvi glavnega ozadja, da bo iluzija popolna. Ta majhna pomanjkljivost je dovolj, da naredim kodo bolj zapleteno v zameno za resnično preglednost, neodvisno od ozadja. Ne pravim, da je pristop k meji slab ali napačen. Priporočil bi ga v večini primerov, kjer je ozadje znano. Toda tukaj smo, da raziskujemo nove stvari in, kar je najpomembneje, gradimo komponente, ki niso odvisne od svojega okolja.
Tokrat poskusimo z drugo obliko:
Tokrat smo ugnezdeno sliko naredili krog namesto kvadrata. To je lahka naloga border-radius
Vendar moramo uporabiti a krožni izrez za ostale slike. Tokrat pa se bomo oprli na a radial-gradient()
namesto a conic-gradient()
da bi dobili ta lep zaobljen videz.
.gallery > img {
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2), #000 calc(51% + var(--g)/2));
}
.gallery > img:nth-child(1) { --_a: calc(100% + var(--g)/2) calc(100% + var(--g)/2); }
.gallery > img:nth-child(2) { --_a: calc(0% - var(--g)/2) calc(100% + var(--g)/2); }
.gallery > img:nth-child(3) { --_a: calc(100% + var(--g)/2) calc(0% - var(--g)/2); }
.gallery > img:nth-child(4) { --_a: calc(0% - var(--g)/2) calc(0% - var(--g)/2); }
Vse slike uporabljajo enako konfiguracijo kot prejšnji primer, vendar vsakič posodobimo središčno točko.
Zgornja slika prikazuje središčno točko za vsak krog. Kljub temu boste v dejanski kodi opazili, da upoštevam tudi vrzel, da zagotovim, da so vse točke na istem položaju (središče mreže), da dobimo neprekinjen krog, če jih združimo.
Zdaj, ko imamo našo postavitev, se pogovorimo o učinku lebdenja. Če niste opazili, kul učinek lebdenja poveča velikost ugnezdene slike in ustrezno prilagodi vse ostalo. Povečanje velikosti je razmeroma lahka naloga, vendar je posodabljanje preliva bolj zapleteno, saj prelivov privzeto ni mogoče animirati. Da bi to premagal, bom uporabil a font-size
kramp, da bi lahko animirali radialni gradient.
Če preverite kodo gradienta, lahko vidite, da dodajam 1em
:
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2 + 1em), #000 calc(51% + var(--g)/2 + 1em));
To je znano em
enote so relativne glede na nadrejeni element font-size
, tako spreminjanje font-size
od .gallery
bo spremenilo tudi izračunano em
vrednost — to je trik, ki ga uporabljamo. Animiramo font-size
od vrednosti 0
na dano vrednost in posledično je gradient animiran, zaradi česar se izrezani del poveča in sledi velikosti ugnezdene slike, ki postaja večja.
Tukaj je koda, ki poudarja dele, vključene v učinek lebdenja:
.gallery {
--s: 200px; /* controls the image size */
--g: 10px; /* controls the gaps between images */
font-size: 0; /* initially we have 1em = 0 */
transition: .5s;
}
/* we increase the cut-out by 1em */
.gallery > img {
mask:
radial-gradient(farthest-side at var(--_a),
#0000 calc(50% + var(--g)/2 + 1em), #000 calc(51% + var(--g)/2 + 1em));
}
/* we increase the size by 2em */
.gallery > img:nth-child(5) {
width: calc(var(--s) + 2em);
}
/* on hover 1em = S/5 */
.gallery:hover {
font-size: calc(var(--s) / 5);
}
O font-size
trik je koristen, če želimo animirati prelive ali druge lastnosti, ki jih ni mogoče animirati. Lastnosti po meri, definirane z @property, lahko rešijo takšno težavo, vendar podpora za to v času pisanja še manjka.
Odkril sem font-size
trik iz @SelenIT2 med poskusom reševanja izziv na Twitterju.
Druga oblika? Pojdimo!
Tokrat smo ugnezdeno sliko odrezali v obliko romba. Dovolil vam bom, da secirate kodo kot vajo, da ugotovite, kako smo prišli sem. Opazili boste, da je struktura enaka kot v naših primerih. Edine razlike so v tem, kako uporabljamo gradient za ustvarjanje oblike. Poglobite se in se učite!
Krožna slikovna mreža
Lahko združimo, kar smo se naučili tukaj in v prejšnjih člankih, da naredimo še bolj razburljivo slikovno mrežo. Tokrat naj bodo vse slike v naši mreži okrogle in pri lebdenju razširimo sliko, da razkrijemo celotno stvar, saj pokriva preostale fotografije.
Struktura mreže HTML in CSS ni nič novega od prej, zato preskočimo ta del in se raje osredotočimo na želeno krožno obliko in učinek lebdenja.
Uporabili bomo clip-path
in njegove circle()
deluje na — uganili ste! — izreži krog iz slik.
Ta številka ponazarja clip-path
uporabljeno za prvo sliko. Leva stran prikazuje začetno stanje slike, desna pa stanje lebdenja. Lahko uporabiš to spletno orodje igrati in vizualizirati clip-path
vrednosti.
Za druge slike lahko posodobimo sredino kroga (70% 70%
), da dobite naslednjo kodo:
.gallery > img:hover {
--_c: 50%; /* same as "50% at 50% 50%" */
}
.gallery > img:nth-child(1) {
clip-path: circle(var(--_c, 55% at 70% 70%));
}
.gallery > img:nth-child(2) {
clip-path: circle(var(--_c, 55% at 30% 70%));
}
.gallery > img:nth-child(3) {
clip-path: circle(var(--_c, 55% at 70% 30%));
}
.gallery > img:nth-child(4) {
clip-path: circle(var(--_c, 55% at 30% 30%));
}
Upoštevajte, kako definiramo clip-path
vrednosti kot nadomestni del znotraj var()
. Na ta način lahko lažje posodobimo vrednost ob lebdenju z nastavitvijo vrednosti --_c
spremenljivka. Pri uporabi circle()
, je privzeti položaj središčne točke 50% 50%
, zato lahko to izpustimo zaradi bolj jedrnate kode. Zato vidite, da samo nastavljamo 50%
Namesto 50% at 50% 50%
.
Nato povečamo velikost naše slike ob lebdenju na celotno velikost mreže, da lahko pokrijemo druge slike. Zagotavljamo tudi z-index
ima višjo vrednost na lebdeči sliki, zato je najvišja v naši kontekst zlaganja.
.gallery {
--s: 200px; /* controls the image size */
--g: 8px; /* controls the gap between images */
display: grid;
grid: auto-flow var(--s) / repeat(2, var(--s));
gap: var(--g);
}
.gallery > img {
width: 100%;
aspect-ratio: 1;
cursor: pointer;
z-index: 0;
transition: .25s, z-index 0s .25s;
}
.gallery > img:hover {
--_c: 50%; /* change the center point on hover */
width: calc(200% + var(--g));
z-index: 1;
transition: .4s, z-index 0s;
}
.gallery > img:nth-child(1){
clip-path: circle(var(--_c, 55% at 70% 70%));
place-self: start;
}
.gallery > img:nth-child(2){
clip-path: circle(var(--_c, 55% at 30% 70%));
place-self: start end;
}
.gallery > img:nth-child(3){
clip-path: circle(var(--_c, 55% at 70% 30%));
place-self: end start;
}
.gallery > img:nth-child(4){
clip-path: circle(var(--_c, 55% at 30% 30%));
place-self: end;
}
Kaj se dogaja z
place-self
lastnina? Zakaj jo potrebujemo in zakaj ima vsaka slika določeno vrednost?
Se spomnite težave, ki smo jo imeli v prejšnjem članku, ko ustvarjanje mreže koščkov sestavljanke? Povečali smo velikost slik, da bi ustvarili prelivanje, vendar prelivanje nekaterih slik ni bilo pravilno. Popravili smo jih s pomočjo place-self
nepremičnine.
Ista težava tukaj. Povečujemo velikost slik, tako da vsaka presega mrežne celice. Če pa ne storimo ničesar, se bodo vsi prelili na desni in spodnji strani mreže. Kar potrebujemo je:
- prva slika, ki prestopi spodnji desni rob (privzeto vedenje),
- druga slika, ki prehaja čez spodnji levi rob,
- tretja slika prek zgornjega desnega roba in
- četrta slika, ki prehaja čez zgornji levi rob.
Da bi to dosegli, moramo vsako sliko pravilno postaviti z uporabo place-self
nepremičnine.
V primeru, da niste seznanjeni place-self
, to je okrajšava za justify-self
in align-self
za postavitev elementa vodoravno in navpično. Ko zavzame eno vrednost, obe poravnavi uporabita isto vrednost.
Razširitev slikovnih plošč
V prejšnjem članku, ustvaril sem kul učinek povečave, ki velja za mrežo slik, kjer lahko nadziramo vse: število vrstic, število stolpcev, velikosti, faktor lestvice itd.
Poseben primer so bili klasični ekspandirani paneli, kjer imamo samo eno vrsto in kontejner polne širine.
Vzeli bomo ta primer in ga združili z oblikami!
Preden nadaljujemo, toplo priporočam branje mojega drug članek razumeti, kako delujejo triki, ki jih bomo obravnavali. Preverite to in tukaj se bomo osredotočili na ustvarjanje oblik plošče.
Najprej začnimo s poenostavitvijo kode in odstranitvijo nekaterih spremenljivk
Potrebujemo samo eno vrstico, število stolpcev pa se mora prilagoditi glede na število slik. To pomeni, da ne potrebujemo več spremenljivk za število vrstic (--n
) in stolpce (--m
), vendar moramo uporabiti grid-auto-flow: column
, kar omogoča mreži, da samodejno ustvari stolpce, ko dodamo nove slike. Upoštevali bomo fiksno višino za našo posodo; privzeto bo v polni širini.
Izrežimo slike v poševno obliko:
Še enkrat, vsaka slika je v svoji mrežni celici, tako da je med slikami več prostora, kot bi si želeli:
Povečati moramo širino slik, da ustvarimo prekrivanje. Zamenjamo min-width:
100%
z min-width: calc(100% + var(--s))
, Kjer --s
je nova spremenljivka, ki nadzoruje obliko.
Zdaj moramo popraviti prvo in zadnjo sliko, tako da bosta brez vrzeli izstopali s strani. Z drugimi besedami, odstranimo lahko naklon z leve strani prve slike in naklon z desne strani zadnje slike. Potrebujemo novo clip-path
posebej za ti dve sliki.
Odpraviti moramo tudi prelivanje. Privzeto se bodo vse slike prelivale na obeh straneh, vendar za prvo potrebujemo preliv na desni strani, medtem ko potrebujemo levi preliv za zadnjo sliko.
.gallery > img:first-child {
min-width: calc(100% + var(--s)/2);
place-self: start;
clip-path: polygon(0 0,100% 0,calc(100% - var(--s)) 100%,0 100%);
}
.gallery > img:last-child {
min-width: calc(100% + var(--s)/2);
place-self: end;
clip-path: polygon(var(--s) 0,100% 0,100% 100%,0 100%);
}
Končni rezultat je lepa razširljiva plošča poševnih slik!
Dodamo lahko poljubno število slik in mreža se bo samodejno prilagodila. Poleg tega moramo nadzorovati samo eno vrednost za nadzor oblike!
To isto postavitev bi lahko naredili s flexboxom, saj imamo opravka z eno samo vrsto elementov. Tukaj je moja izvedba.
Seveda so poševne slike kul, kaj pa cik-cak vzorec? Tega sem že dražil pri konec zadnjega članka.
Vse, kar počnem tukaj, je zamenjava clip-path
z mask
… in ugani kaj? Imam že podroben članek o ustvarjanje te cik-cak oblike — da ne omenjam spleta generator, da dobite kodo. Vidite, kako se vse skupaj sestavi?
Najtežji del tukaj je zagotoviti, da so cik-cak popolnoma poravnani, za to pa moramo dodati odmik za vsak :nth-child(odd)
slikovni element.
.gallery > img {
mask:
conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg)
100% calc(50% + var(--_p, 0%))/51% calc(2*var(--s)) repeat-y,
conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg)
0% calc(50% + var(--_p, 0%))/51% calc(2*var(--s)) repeat-y;
}
/* we add an offset to the odd elements */
.gallery > img:nth-child(odd) {
--_p: var(--s);
}
.gallery > img:first-child {
mask:
conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg)
0 calc(50% + var(--_p, 0%))/100% calc(2*var(--s));
}
.gallery > img:last-child {
mask:
conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg)
0 calc(50% + var(--_p, 0%)) /100% calc(2*var(--s));
}
Upoštevajte uporabo --_p
spremenljivka, ki bo padla nazaj na 0%
vendar bo enako --_s
za čudne slike.
Tukaj je predstavitev, ki ponazarja težavo. Premaknite miškin kazalec, da vidite, kako je odmik — definiran z --_p
— popravlja poravnavo.
Opazite tudi, kako uporabljamo različno masko za prvo in zadnjo sliko, kot smo to storili v prejšnjem primeru. Potrebujemo samo cik-cak na desni strani prve slike in levi strani zadnje slike.
In zakaj ne zaobljene stranice? Naredimo to!
Vem, da je koda morda videti strašljiva in težka za razumevanje, toda vse, kar se dogaja, je kombinacija različnih trikov, ki smo jih obravnavali v tem in drugih člankih, ki sem jih že delil. V tem primeru uporabljam isto strukturo kode kot cik-cak in poševne oblike. Primerjajte s temi primeri in ne boste našli nobene razlike! To so isti triki moj prejšnji članek o učinku povečave. Potem uporabljam svoj drugo pisanje in moj spletni generator da dobite kodo za masko, ki ustvari te zaobljene oblike.
Če se spomnite, kaj smo naredili za cik-cak, smo uporabili isto masko za vse slike, nato pa smo morali nenavadnim slikam dodati odmik, da smo ustvarili popolno prekrivanje. V tem primeru potrebujemo drugačno masko za liho oštevilčene slike.
Prva maska:
mask:
linear-gradient(-90deg,#0000 calc(2*var(--s)),#000 0) var(--s),
radial-gradient(var(--s),#000 98%,#0000) 50% / calc(2*var(--s)) calc(1.8*var(--s)) space repeat;
Drugi:
mask:
radial-gradient(calc(var(--s) + var(--g)) at calc(var(--s) + var(--g)) 50%,#0000 98% ,#000)
calc(50% - var(--s) - var(--g)) / 100% calc(1.8*var(--s))
Edini trud, ki sem ga naredil tukaj, je posodobitev druge maske, da vključuje spremenljivko vrzeli (--g
), da ustvarite ta prostor med slikami.
Zadnji dotik je popraviti prvo in zadnjo sliko. Kot vsi prejšnji primeri, prva slika potrebuje raven levi rob, medtem ko zadnja potrebuje raven desni rob.
Za prvo sliko vedno vemo masko, ki jo mora imeti, in sicer:
.gallery > img:first-child {
mask:
radial-gradient(calc(var(--s) + var(--g)) at right, #0000 98%, #000) 50% / 100% calc(1.8 * var(--s));
}
Za zadnjo sliko je odvisno od števila elementov, tako da je pomembno, če je ta element :nth-child(odd)
or :nth-child(even)
.
.gallery > img:last-child:nth-child(even) {
mask:
linear-gradient(to right,#0000 var(--s),#000 0),
radial-gradient(var(--s),#000 98%,#0000) left / calc(2*var(--s)) calc(1.8*var(--s)) repeat-y
}
.gallery > img:last-child:nth-child(odd) {
mask:
radial-gradient(calc(var(--s) + var(--g)) at left,#0000 98%,#000) 50% / 100% calc(1.8*var(--s))
}
To je vse! Tri različne postavitve, vendar vsakič isti triki CSS:
- strukturo kode za ustvarjanje učinka povečave
- masko ali izrezno pot za ustvarjanje oblik
- ločeno konfiguracijo za čudne elemente v nekaterih primerih, da zagotovimo popolno prekrivanje
- posebna konfiguracija za prvo in zadnjo sliko, da ohrani obliko samo na eni strani.
In tukaj je velik demo z vsemi skupaj. Vse kar potrebujete je, da dodate razred, da aktivirate postavitev, ki jo želite videti.
In tukaj je tisti z implementacijo Flexbox
Zavijanje
Uf, končali smo! Vem, da je med tem člankom in zadnjim veliko trikov in primerov CSS, da ne omenjam vseh drugih trikov, ki sem jih tukaj navedel iz drugih člankov, ki sem jih napisal. Potreboval sem čas, da sem vse sestavil, in ni treba razumeti vsega naenkrat. Eno branje vam bo dalo dober pregled nad vsemi postavitvami, vendar boste morda morali članek prebrati večkrat in se osredotočiti na vsak primer, da boste razumeli vse trike.
Ste opazili, da se HTML-ja sploh nismo dotaknili, razen morda števila slik v označbi? Vse postavitve, ki smo jih naredili, imajo skupno kodo HTML, ki ni nič drugega kot seznam slik.
Preden končam, vam bom pustil še zadnji primer. Je »proti« med dvema anime likoma s kul učinkom lebdenja.
Kaj pa ti? Ali lahko ustvarite nekaj na podlagi tega, kar ste se naučili? Ni treba, da je zapleteno – predstavljajte si nekaj kul ali smešnega, kot sem jaz s tisto anime tekmo. To je lahko dobra vaja za vas in morda zaključimo z odlično zbirko v oddelku za komentarje.