Cărți Magic Flip: Rezolvarea unei probleme comune de dimensionare
Publicat: 2022-03-10Care sunt șansele următorului tău client să folosească cuvântul interactiv în timp ce își prezintă proiectul? Din experiența mea, răspunsul este 100% , așa că sunt mereu în căutarea unor tehnici CSS robuste care să mă ajute să ofer diferitele caracteristici și efecte care apar atunci când discutăm despre acest obiectiv.
O mică parte de interactivitate pe care mi se cere să o implementez din nou și din nou sunt cărțile răsturnate - blocuri de conținut care se rotesc atunci când trec cu mouse-ul sau ating pentru a dezvălui conținut pe verso. Este un efect îngrijit care încurajează navigarea jucăușă și o altă modalitate de a afișa mai multe informații fără a naviga în afara paginii. Dar metoda standard are o problemă atunci când vine vorba de acomodarea diferitelor lungimi de conținut de card.
În acest tutorial, vom construi o grilă de card flip care rezolvă această problemă cu unele elemente de bază CSS - transformări, flexibilitate și grilă. Va trebui să vă familiarizați cu acestea și vă va ajuta să aveți o bună înțelegere a tehnicilor de poziționare CSS. Vom acoperi:
- Cum sunt implementate de obicei cardurile flip folosind poziționarea absolută;
- Problema de dimensionare pe care o introduce poziționarea absolută; și
- O soluție generală pentru dimensionarea automată a conținutului suprapus.
Crearea unui card de bază flip
Cu un browser modern bun pentru transformări tridimensionale, crearea unui card de bază este relativ simplă. Metoda obișnuită este să plasați fețele din față și din spate într-un container pentru părinte și să poziționați absolut fața din spate, astfel încât să se potrivească cu dimensiunea feței din față. Adăugați o transformare pe axa x pe fața din spate pentru a o face să pară inversată, adăugați o altă transformare pe card în sine la trecerea cu mouse-ul și suntem în afaceri.
.cards { display: grid; } .card { perspective: 40rem; } .card-body { transform-style: preserve-3d; transition: var(--time) transform; .card:hover & { transform: rotateX(-180deg); } } .card-front, .card-back { backface-visibility: hidden; } .card-back { position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform: rotateX(-180deg); }
Ce ar putea merge prost?
Soluția noastră standard are totuși o mare problemă: nu funcționează atunci când fața din spate are nevoie de mai mult spațiu decât oferă fața frontală. Oferirea cardului de o dimensiune mare, fixă este o soluție, dar această abordare este, de asemenea, garantată să eșueze la un moment dat pentru un anumit set de dimensiuni de ecran.
Compozițiile de design prezintă în mod natural cutii cu aspect îngrijit cu text care se potrivește perfect. Dar atunci când începeți dezvoltarea, poate fi dificil să obțineți o pagină și un aspect de card care să funcționeze pentru conținutul real. Și atunci când afișați conținut dinamic dintr-un CMS, poate fi imposibil! Chiar și cu limite de cuvinte sau de caractere, adesea nu există o soluție care să funcționeze fiabil pe toate dispozitivele.
Ar trebui să ne străduim întotdeauna să creăm implementări de aspect care să tolereze o gamă largă de lungimi de conținut. Dar nu este ușor! Am avut adesea ocazia să mă întorc la utilizarea dimensiunilor și poziției fixe, fie din cauza constrângerilor de timp, a suportului insuficient pentru browser, a unui design de referință slab sau doar a propriei inexperience.
De-a lungul anilor, am învățat că un proces iterativ bun și un dialog sănătos cu designerul pot ajuta foarte mult atunci când discutăm aceste probleme și, adesea, vă puteți întâlni undeva la mijloc pentru a obține un aspect robust, cu o oarecare interactivitate. Dar să revenim la sarcina în cauză - se poate face?
Gândește liber
De fapt, este posibil să dimensionezi cardurile în funcție de conținutul din față și din spate și nu este atât de greu pe cât pare la început. Trebuie doar să fim metodici și perseverenți!
Constrângerea problemei
Să începem prin a face o listă cu cerințele aspectului nostru. Încercarea de a scrie exact ceea ce doriți ar putea părea o corvoadă, dar este o modalitate excelentă de a descoperi constrângeri care pot fi simplificate pentru a rezolva o problemă. Sa spunem:
- Dorim să vedem una sau mai multe carduri dreptunghiulare, aranjate într-o grilă cu o singură coloană sau cu mai multe coloane;
- Dorim ca cardurile să se răstoarne la trecerea cu mouse-ul sau să atingă pentru a dezvălui un al doilea set de conținut pe fața din spate;
- Dorim ca cardurile să fie întotdeauna suficient de mari pentru a arăta tot conținutul din față și din spate, indiferent de lungimea conținutului sau stil; și
- În cazul coloanelor multiple, în mod ideal, dorim ca toate cărțile să aibă aceeași dimensiune, astfel încât rândurile să se alinieze frumos.
Gândindu-ne la aceste cerințe, putem observa câteva lucruri care simplifică problema:
- Dacă cardurile vor fi prezentate într-o grilă, avem o constrângere asupra lățimii lor - adică lățimile lor sunt funcții ale ferestrei de vizualizare sau ale containerului grilă mai degrabă decât propriul conținut;
- Având în vedere că știm lățimea unui card (cel puțin ca procent din părintele său), am rezolvat dimensiunea orizontală și trebuie doar ca înălțimea cardului să se extindă pentru a se potrivi cu cea mai înaltă a feței din față sau din spate; și
- Dacă putem face asta și fiecare card este auto-dimensionat vertical, putem folosi
grid-auto-rows
ale CSS Grid pentru a face toate rândurile de cărți la fel de înalte ca și cea mai înaltă carte.
Descoperirea trucului cărților
Deci, cum autodimensionăm cărțile? Acum ne-am simplificat problema, suntem la îndemâna soluției.
Uită, pentru o clipă, ideea de a pune conținut peste alt conținut și concentrează-te pe noua noastră cerință: un părinte care să fie la fel de înalt ca cel mai înalt copil al său. Asta e ușor! Folosind coloane, putem determina un părinte să se extindă la înălțimea celui mai înalt copil al său. Apoi, trebuie doar să folosim un pic de deleitură pentru a-i alinia pe copii:
- Setați copiii să aibă aceeași lățime ca și părintele lor
- Permite celui de-al doilea copil să se reverse spre dreapta
- Transformați-o spre stânga înapoi la locul său potrivit
.cards { display: grid; } .card-body { display: flex; } .card-front, .card-back { min-width: 100%; mix-blend-mode: multiply; // Preview both faces } .card-back { transform: translate(-100%, 0); }
Dacă această abordare pare evidentă, fiți siguri că am petrecut multe ore trecând prin câteva idei cu adevărat groaznice înainte de a mă gândi la asta. La început, am plănuit să tipărim o versiune duplicată ascunsă a textului feței din spate în interiorul feței frontale pentru a extinde cardul la dimensiunea corectă. Și când m-am gândit să folosesc overflow-ul coloanei, inițial tăiam coloana din dreapta folosind overflow:hidden
și o transformam abia în ultimul moment când a început hover-ul, deoarece încă nu mi-am dat seama că o pot păstra transformată. de la început și utilizați o altă metodă, cum ar fi opacity
sau backface-visibility
pentru a o porni și dezactiva după cum este necesar.
Cu alte cuvinte, soluțiile evidente sunt rezultatul muncii grele! Dacă simțiți că v-ați lovit cu capul de birou ore întregi din cauza unei probleme de aspect, este important să faceți un pas înapoi și să decideți dacă petreceți timpul clientului cu înțelepciune: dacă sugerați ca aceștia să modifice designul și dacă să urmărești soluția în timpul tău ca un exercițiu de învățare când presiunea scade. Dar când vii cu metode simple, nu te simți niciodată prost pentru că a durat mult timp . Acum, să revizuim soluția noastră completă.
.cards { display: grid; } .card { perspective: 40rem; } .card-body { display: flex; transform-style: preserve-3d; transition: var(--time) transform; .card:hover & { transform: rotateX(-180deg); } } .card-front, .card-back { backface-visibility: hidden; min-width: 100%; } .card-back { transform: rotateX(-180deg) translate(-100%, 0); }
Există avertismente?
Soluția funcționează bine în general, cu doar câteva avertismente minore de reținut:
- Cardurile trebuie să fie prezente într-un aspect de grilă sau într-un alt context în care lățimea lor nu depinde de conținut.
- Cardurile necesită un fel de înveliș de conținut (
card-body
nostru), astfel încât zona de hover să nu se schimbe în timpul animațiilor. Dacă cardul în sine este animat, veți vedea unele erori pe măsură ce animația se oprește și repornește rapid. - Stilurile, cum ar fi fundalurile și umbrele casetei, sunt cel mai bine plasate direct pe fețele din față și din spate, deoarece orice efect asupra cardului în sine nu va fi animat. Atenție la stiluri, cum ar fi umbrele casetei de pe corpul cardului, deoarece în mod natural acestea vor fi răsturnate cu susul în jos.
- Fețele din față și din spate ale cărților au nevoie de proprietatea
box-sizing
setată laborder-box
dacă au propria lor umplutură, din cauza cerințeimin-width
, altfel se vor depăși. - Safari necesită încă
-webkit-backface-visibility
, în forma sa prefixată de furnizor.
Adăugând niște poloneză
Acum am rezolvat problema grea, să ne uităm la câteva modificări pe care le putem face pentru ca întreaga interacțiune să funcționeze cât mai bine posibil.
Mai întâi, verificați dacă cărțile se suprapun în timp ce răsturnați. Acest lucru va depinde dacă utilizați mai multe coloane, lățimea jgheabului coloanei, orientarea flipului și valoarea perspectivei cardului, dar este posibil să se întâmple. Puteți crește durata animației pentru a vedea lucrurile mai clar. Când treceți cu mouse-ul, pare nenatural ca cardul plasat să se răstoarne sub vecinii săi mai târziu, așa că trebuie să îl punem deasupra folosind z-index
. Destul de ușor, dar ai grijă! Trebuie să așteptăm până când animația de ieșire este completă înainte de a restaura z-index
. Introduceți transition-delay
:
.card { transition: z-index; transition-delay: var(--time); z-index: 0; &:hover { transition-delay: 0s; z-index: 1; } }
Apoi, luați în considerare crearea unei stări active pentru cărți. De obicei, încerc să fac cărți ca acestea să trimită către un loc relevant – chiar dacă nu sunt specificate de designer – deoarece elementele cu efecte de hover ca acesta se simt foarte ușor de atins, așa că este bine să ofer o destinație pentru cititorii care își încearcă norocul. Îmi place o transformare scurtă, subtilă, la scară, deoarece funcționează destul de bine indiferent dacă a doua jumătate a animației este întreruptă sau nu prin încărcarea paginii de destinație (mi-ar plăcea ca browserele să completeze animațiile în timpul zborului în mod curat înainte de navigare, totuși Sunt sigur că ar fi mult mai dificil de implementat în practică decât pare).
Aceasta este, de asemenea, o oportunitate excelentă de a ne gândi cât de accesibil este conținutul din spate al cardurilor noastre. Marcajul nostru este concis și bine ordonat, așa că am acoperit cititoarele de ecran și alte cazuri de utilizare care ignoră stilul, dar ce zici de utilizatorii de tastatură? Dacă vom face cărțile în sine să fie ancore, acestea vor primi focus ca fila utilizatorilor de tastatură prin pagină. Să reutilizam starea de trecere a cardului ca stare de focalizare, iar conținutul din spate va apărea în mod natural în timpul navigării cu tastatura.
.card { transition: z-index, transform calc(var(--time) / 4); transition-delay: var(--time), 0s; z-index: 0; &:hover { transition-delay: 0s; z-index: 1; } &:active { transform: scale(0.975); } } .card-body { .card:hover &, .card:focus & { transform: rotateX(-180deg); } }
În cele din urmă, nu uitați că acum cardul se scalează automat pentru a se potrivi conținutului său, puteți utiliza aproape orice tehnici de aliniere și spațiere doriți în interiorul containerelor din față și din spate. Folosiți alinierea flexibilă pentru a centra titlurile, adăugați umplutură, chiar și puneți o altă grilă în interiorul cardului. Aceasta este frumusețea soluțiilor de layout bune care se adaptează la conținutul lor - cuplarea redusă a copiilor cu părinți și modularitatea care vă permite să vă concentrați pe un singur lucru la un moment dat.
.card-front, .card-back { display: flex; align-items: center; background-color: white; box-shadow: 0 5px 10px black; border-radius: 0.25rem; padding: 1.5rem; }
Încheierea
Sper că veți găsi utilă această tehnică CSS! De ce să nu încercați câteva variante ale animației, cum ar fi un efect de scară sau un simplu cross-fade? Tehnica nu se limitează nici la factorul de formă a cărților. Poate fi folosit oriunde unde responsabilitatea dimensionarii verticale revine mai multor elemente. Imaginați-vă un site web de revistă care conține fotografii mari cu subtitrări suprapuse - îl puteți folosi pentru a găzdui atât imagini cu raport de aspect înalte, cât și text dinamic lung.
Mai presus de toate, amintiți-vă avantajele de a vă acorda ceva timp pentru a vă gândi cu adevărat dacă există o modalitate de implementare a unui design care arată ca și cum ar funcționa numai cu dimensiuni și poziții fixe. Adesea există, și oricât de dificilă ar părea problema la început, să vă scrieți toate cerințele, să vă puneți ceva timp deoparte pentru a crea un caz de testare minim și să parcurgeți metodic este întotdeauna cel mai bun pariu.