Creați efecte de imagine receptive cu degrade CSS și raport de aspect
Publicat: 2022-03-10aspect-ratio
nou acceptată în combinație cu object-fit
oferă un remediu pentru această durere de cap a trecutului! Să învățăm să folosim aceste proprietăți, pe lângă crearea unui efect de imagine gradient receptiv pentru un plus de fler.Pentru a ne pregăti pentru viitoarele efecte de imagine, vom configura o componentă de card care are o imagine mare în partea de sus, urmată de un titlu și descriere. Problema comună cu această configurație este că este posibil să nu avem întotdeauna controlul perfect asupra a ceea ce este imaginea și, mai important, pentru aspectul nostru, care sunt dimensiunile acesteia. Și, deși acest lucru poate fi rezolvat prin decuparea din timp, putem întâmpina probleme din cauza containerelor de dimensiuni adecvate. O consecință este pozițiile inegale ale conținutului cardului, care iese cu adevărat în evidență atunci când prezentați un rând de cărți.
O altă soluție anterioară, pe lângă decuparea, ar fi putut fi schimbarea de la o imagine img
la un div
gol care exista doar pentru a prezenta imaginea prin imaginea background-image
. Am implementat această soluție de multe ori în trecut. Un avantaj pe care îl are este utilizarea unui truc mai vechi pentru raportul de aspect, care utilizează un element de înălțime zero și setează o valoare padding-bottom
. Setarea unei valori de umplutură ca procent are ca rezultat o valoare finală calculată care este relativă la lățimea elementului. Este posibil să fi folosit și această idee pentru a menține un raport de 16:9 pentru încorporarea videoclipurilor, caz în care valoarea de umplutură se găsește cu formula: 9/16 = 0.5625 * 100% = 56.26%
. Dar vom explora două proprietăți CSS moderne care nu implică matematică suplimentară, ne oferă mai multă flexibilitate și, de asemenea, permit păstrarea semanticii furnizate prin utilizarea unui img
real în loc de un div
gol.
Mai întâi, să definim semantica HTML, inclusiv utilizarea unei liste neordonate ca container pentru carduri:
<ul class="card-wrapper"> <li class="card"> <img src="" alt=""> <h3>A Super Wonderful Headline</h3> <p>Lorem ipsum sit dolor amit</p> </li> <!-- additional cards --> </ul>
În continuare, vom crea un set minim de stiluri de bază pentru componenta .card
. Vom seta câteva stiluri vizuale de bază pentru cardul în sine, o actualizare rapidă a titlului h3
așteptat, apoi stiluri esențiale pentru a începe să stilăm imaginea cardului.
.card { background-color: #fff; border-radius: 0.5rem; box-shadow: 0.05rem 0.1rem 0.3rem -0.03rem rgba(0, 0, 0, 0.45); padding-bottom: 1rem; } .card > :last-child { margin-bottom: 0; } .card h3 { margin-top: 1rem; font-size: 1.25rem; } img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; } img ~ * { margin-left: 1rem; margin-right: 1rem; }
Ultima regulă folosește combinatorul general de frați pentru a adăuga o marjă orizontală oricărui element care urmează img
, deoarece dorim ca imaginea în sine să fie la același nivel cu părțile laterale ale cardului.
Și progresul nostru de până acum ne conduce la următoarea apariție a cărților:
În cele din urmă, vom crea stilurile .card-wrapper
pentru un aspect rapid receptiv folosind grila CSS. Acest lucru va elimina și stilurile implicite ale listei.
.card-wrapper { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr)); grid-gap: 1.5rem; }
Notă : Dacă această tehnică de grilă nu vă este familiară, consultați explicația din tutorialul meu despre soluțiile moderne pentru grila cu 12 coloane.
Cu acest lucru aplicat și cu toate cardurile care conțin o imagine cu o cale sursă validă, stilurile noastre .card-wrapper
ne oferă următorul aspect:
După cum se demonstrează în imaginea de previzualizare, aceste stiluri de bază nu sunt suficiente pentru a conține imaginile în mod corespunzător, având în vedere dimensiunile lor naturale diferite. Avem nevoie de o metodă pentru a constrânge aceste imagini în mod uniform și consecvent.
Activați Dimensiunile uniforme ale imaginii cu object-fit
După cum sa menționat mai devreme, este posibil să fi efectuat anterior o actualizare în acest scenariu pentru a modifica imaginile care urmează să fie adăugate prin background-image
și ați folosit background-size: cover
pentru a gestiona frumos redimensionarea imaginii. Sau poate ați încercat să impuneți tăierea din timp (încă un obiectiv demn, deoarece orice reducere a dimensiunii imaginii va îmbunătăți performanța!).
Acum, avem disponibilă proprietatea object-fit
care permite unei etichete img
să acționeze ca container pentru imagine. Și, vine și cu o valoare de cover
, care are ca rezultat un efect similar cu soluția de imagine de fundal, dar cu bonusul de a păstra semantica unei imagini în linie. Să-l aplicăm și să vedem cum funcționează.
Trebuie să-l împerechem cu o dimensiune de height
pentru îndrumare suplimentară cu privire la modul în care dorim să se comporte containerul de imagine (reamintim că am adăugat deja width: 100%
). Și vom folosi funcția max()
pentru a selecta fie 10rem
, fie 30vh
în funcție de care este mai mare într-un context dat, ceea ce împiedică înălțimea imaginii să se micșoreze prea mult pe ferestre mai mici sau când utilizatorul a setat un zoom mare.
img { /* ...existing styles */ object-fit: cover; height: max(10rem, 30vh); }
Sfat de accesibilitate bonus : ar trebui să testați întotdeauna machetele cu zoom de 200% și 400% pe desktop. Deși în prezent nu există o interogare media zoom
, funcții precum max()
pot ajuta la rezolvarea problemelor de aspect. Un alt context pe care această tehnică este utilă este distanța dintre elemente.
Cu această actualizare, am îmbunătățit cu siguranță lucrurile, iar rezultatul vizual este ca și cum am folosi tehnica mai veche a imaginii de fundal:
Dimensiunea imaginii în mod receptiv și consistentă cu aspect-ratio
Când folosiți object-fit
în sine, un dezavantaj este că mai trebuie să setăm câteva indicii de dimensiune.
O proprietate viitoare (disponibilă în prezent în browserele Chromium) numită aspect-ratio
va îmbunătăți capacitatea noastră de a dimensiona în mod constant imaginile.
Folosind această proprietate, putem defini un raport pentru a redimensiona imaginea în loc să setăm dimensiuni explicite. Vom continua să-l folosim în combinație cu object-fit
pentru a ne asigura că aceste dimensiuni afectează doar imaginea ca container, în caz contrar, imaginea ar putea apărea distorsionată.
Iată regula noastră completă pentru imagini actualizate:
img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; object-fit: cover; aspect-ratio: 4/3; }
Vom începe cu un raport de imagine de 4 ⁄ 3 pentru contextul cardului nostru, dar puteți alege orice raport. De exemplu, 1 ⁄ 1 pentru un pătrat sau 16 ⁄ 9 pentru încorporarea video standard.
Iată cardurile actualizate, deși probabil va fi dificil de observat diferența vizuală în acest caz particular, deoarece raportul de aspect se întâmplă să se potrivească îndeaproape cu aspectul pe care l-am obținut prin setarea height
numai pentru object-fit
.
Setarea unui „raport de aspect” are ca rezultat menținerea raportului pe măsură ce elementele cresc sau se micșorează, în timp ce atunci când setați doar „potrivire obiect” și „înălțime”, raportul imaginii va fi în mod constant în flux pe măsură ce dimensiunile containerului se schimbă.
„
Adăugarea de efecte receptive cu degrade și funcții CSS
OK, acum că știm cum să setăm imagini de dimensiuni constante, să ne distrăm puțin cu ele adăugând un efect de gradient!
Scopul nostru cu acest efect este să facem să pară ca și cum imaginea se estompează în conținutul cardului. S-ar putea să fiți tentat să înfășurați imaginea în propriul container pentru a adăuga gradient, dar datorită muncii pe care am făcut-o deja cu privire la dimensionarea imaginii, putem găsi cum să o facem în siguranță pe .card
principal .
Primul pas este definirea unui gradient . Vom folosi o proprietate personalizată CSS pentru a adăuga culorile gradientului pentru a permite schimbarea cu ușurință a efectului de gradient, începând cu albastru la roz. Ultima culoare din gradient va fi întotdeauna albă pentru a menține tranziția în fundalul conținutului cardului și pentru a crea marginea „pene”.
.card { --card-gradient: #5E9AD9, #E271AD; background-image: linear-gradient( var(--card-gradient), white max(9.5rem, 27vh) ); /* ...existing styles */ }
Dar așteptați - este o funcție CSS max()
? Într-un gradient? Da, este posibil și magia este cea care face ca acest gradient să răspundă eficient!
Cu toate acestea, dacă ar fi să adaug o captură de ecran, nu am vedea de fapt că gradientul are vreun efect asupra imaginii. Pentru aceasta, trebuie să introducem proprietatea mix-blend-mode
și, în acest scenariu, vom folosi valoarea de overlay
:
img { /* ...existing styles */ mix-blend-mode: overlay; }
Proprietatea mix-blend-mode
este similară cu aplicarea stilurilor de amestecare a straturilor disponibile în software-ul de manipulare a fotografiilor, cum ar fi Photoshop. Și valoarea de overlay
va avea efectul de a permite tonurilor medii din imagine să se amestece cu gradientul din spatele acesteia, ducând la următorul rezultat:
Acum, în acest moment, ne bazăm doar pe valoarea aspect-ratio
pentru a redimensiona imaginea. Și dacă redimensionăm containerul și facem ca aspectul cardului să revină, schimbarea înălțimii imaginii provoacă inconsecvențe în cazul în care gradientul devine alb.
Deci vom adăuga și o proprietate max-height
care folosește și funcția max()
și conține valori puțin mai mari decât cele din gradient. Comportamentul rezultat este că gradientul se va alinia corect (aproape întotdeauna) cu partea de jos a imaginii.
img { /* ...existing styles */ max-height: max(10rem, 30vh); }
Este important de reținut că adăugarea unei „înălțimi maxime” modifică comportamentul „raportului de aspect”. În loc să se folosească întotdeauna raportul exact, acesta va fi folosit numai atunci când există suficient spațiu alocat, având în vedere noua constrângere suplimentară a „înălțimii maxime”.
„
Cu toate acestea, aspect-ratio
va continua să asigure redimensionarea în mod constant a imaginilor, așa cum a fost beneficiul față de numai object-fit
. Încercați să comentați aspect-ratio
în demonstrația finală CodePen pentru a vedea diferența pe care o face în funcție de dimensiunile containerelor.
Întrucât obiectivul nostru inițial a fost să permitem dimensiunile imaginii receptive în mod constant , am ajuns în continuare la obiectiv. Pentru propriul dvs. caz de utilizare, poate fi necesar să vă jucați cu valorile raportului și al înălțimii pentru a obține efectul dorit.
Alternativ: mix-blend-mode
și adăugarea unui filtru
Folosirea overlay
ca valoare a mix-blend-mode
a fost cea mai bună alegere pentru efectul de estompare în alb pe care îl căutam, dar haideți să încercăm o opțiune alternativă pentru un efect mai dramatic.
Vom actualiza soluția noastră pentru a adăuga o proprietate personalizată CSS pentru valoarea mix-blend-mode
și, de asemenea, vom actualiza valorile de culoare pentru gradient:
.card { --card-gradient: tomato, orange; --card-blend-mode: multiply; } img { /* ...existing styles */ mix-blend-mode: var(--card-blend-mode); }
Valoarea de multiply
are un efect de întunecare a tonurilor medii, dar păstrează albul și negru așa cum este, rezultând următorul aspect:
Deși am pierdut decolorarea și acum avem o margine dură în partea de jos a imaginii, partea albă a gradientului nostru este încă importantă pentru a ne asigura că gradientul se termină înainte de conținutul cardului.
O modificare suplimentară pe care o putem adăuga este utilizarea filter
și, în special, utilizarea funcției grayscale()
pentru a elimina culorile imaginii și, prin urmare, pentru ca gradientul să fie singura sursă de colorare a imaginii.
img { /* ...existing styles */ filter: grayscale(100); }
Utilizarea valorii tonurilor de grayscale(100)
are ca rezultat eliminarea completă a culorilor naturale ale imaginii și transformarea acesteia în alb-negru. Iată actualizarea pentru comparație cu captura de ecran anterioară a efectului său atunci când folosiți gradientul nostru portocaliu cu multiply
:
Utilizați aspect-ratio
ca îmbunătățire progresivă
După cum sa menționat anterior, în prezent aspect-ratio
este acceptat numai în cea mai recentă versiune a browserelor Chromium (Chrome și Edge). Cu toate acestea, toate browserele acceptă object-fit
și asta, împreună cu constrângerile noastre de height
, are ca rezultat un rezultat mai puțin ideal, dar totuși acceptabil, văzut aici pentru Safari:
Fără funcționarea aspect-ratio
, rezultatul aici este că în cele din urmă înălțimea imaginii este limitată, dar dimensiunile naturale ale fiecărei imagini conduc încă la o oarecare variație între înălțimile imaginii cardului. Poate doriți să treceți la adăugarea unei max-height
sau să utilizați din nou funcția max()
pentru a face o max-height
mai receptivă la diferite dimensiuni de card.
Extinderea efectelor de gradient
Deoarece am definit opririle de culoare gradient ca o proprietate personalizată CSS, avem acces facil pentru a le modifica în diferite contexte. De exemplu, am putea schimba gradientul pentru a prezenta mai puternic una dintre culori dacă cardul este plasat cu mouse-ul sau are unul dintre copiii săi focalizat.
În primul rând, vom actualiza fiecare card h3
pentru a conține un link, cum ar fi:
<h3><a href="">A Super Wonderful Headline</a></h3>
Apoi, putem folosi unul dintre cele mai noi selectoare disponibile — :focus-within
— pentru a modifica gradientul cardului atunci când legătura este focalizată. Pentru o acoperire suplimentară a posibilelor interacțiuni, vom cupla acest lucru cu :hover
. Și, vom reutiliza ideea noastră max()
pentru a atribui o singură culoare pentru a prelua acoperirea porțiunii de imagine a cardului. Dezavantajul acestui efect special este că opririle gradientului și schimbările de culoare nu pot fi animate în mod fiabil - dar vor fi în curând datorită CSS Houdini.
Pentru a actualiza culoarea și a adăuga noua oprire de culoare, trebuie doar să reatribuim valoarea --card-gradient
în cadrul acestei noi reguli:
.card:focus-within, .card:hover { --card-gradient: #24a9d5 max(8.5rem, 20vh); }
Valorile noastre max()
sunt mai mici decât originalul utilizat pentru white
pentru a menține marginea pene. Dacă am folosi aceleași valori, s-ar întâlni white
și ar crea o separare clară a dreptului.
În crearea acestei demonstrații, am încercat inițial un efect care folosea transform
cu scale
pentru un efect de mărire. Dar am descoperit că, din cauza mix-blend-mode
aplicat, browserul nu va revopsi în mod constant imaginea, ceea ce a provocat o pâlpâire neplăcută. Vor exista întotdeauna compromisuri în a solicita browserului să efectueze numai efecte și animații CSS și, deși este foarte bine ceea ce putem face, este întotdeauna cel mai bine să verificați impactul asupra performanței al efectelor dvs.
Distrează-te experimentând!
CSS modern ne-a oferit câteva instrumente minunate pentru actualizarea setului nostru de instrumente pentru design web, aspect-ratio
fiind cea mai recentă adăugare. Așa că mergeți mai departe și experimentați cu object-fit
, aspect-ratio
și adăugarea de funcții precum max()
în gradienții dvs. pentru niște efecte distractive de răspuns! Asigurați-vă că verificați din nou lucrurile pe mai multe browsere (deocamdată!) și în diferite ferestre de vizualizare și dimensiuni de containere.
Iată CodePen-ul, inclusiv caracteristicile și efectele pe care le-am analizat astăzi:
Cauți mai mult? Asigurați-vă că consultați Ghidul nostru CSS aici pe Smashing →