Carte Magic Flip: Risolvere un problema di dimensionamento comune
Pubblicato: 2022-03-10Quali sono le possibilità che il tuo prossimo cliente utilizzi la parola interattivo mentre presenta il suo progetto? Nella mia esperienza, la risposta è 100% , quindi sono sempre alla ricerca di solide tecniche CSS che mi aiutino a fornire le varie funzionalità ed effetti che emergono quando discuto di questo obiettivo.
Un piccolo pezzo di interattività che mi viene chiesto di implementare ancora e ancora è il flip card: blocchi di contenuto che si girano quando vengono spostati o toccati per rivelare il contenuto sul retro. È un effetto pulito che incoraggia la navigazione giocosa e un altro modo per mostrare più informazioni senza allontanarsi dalla pagina. Ma il metodo standard ha un problema quando si tratta di adattarsi a diverse lunghezze del contenuto della carta.
In questo tutorial, creeremo una griglia di flip card che risolve questo problema con alcune nozioni di base sui CSS: trasformazioni, flessione e griglia. Avrai bisogno di avere familiarità con questi e ti aiuterà ad avere una buona conoscenza delle tecniche di posizionamento CSS. Copriremo:
- Come le flip card vengono solitamente implementate utilizzando il posizionamento assoluto;
- Il problema di dimensionamento che introduce il posizionamento assoluto; e
- Una soluzione generale per il dimensionamento automatico dei contenuti sovrapposti.
Creazione di una scheda flip di base
Con un buon supporto del browser moderno per le trasformazioni tridimensionali, la creazione di una scheda flip di base è relativamente semplice. Il metodo usuale consiste nel posizionare le facce della carta anteriore e posteriore in un contenitore principale e posizionare assolutamente la faccia posteriore in modo che possa corrispondere alle dimensioni della faccia anteriore. Aggiungi una trasformazione dell'asse x alla faccia posteriore per farla sembrare invertita, aggiungine un'altra alla carta stessa al passaggio del mouse e siamo in affari.
.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); }
Cosa potrebbe andare storto?
La nostra soluzione standard ha un grosso problema, però: non funziona quando la parte posteriore ha bisogno di più spazio di quella fornita dalla parte anteriore. Dare alla scheda una dimensione fissa grande è una soluzione, ma è anche garantito che questo approccio fallirà a un certo punto per alcune serie di dimensioni dello schermo.
Le composizioni di design presentano naturalmente riquadri dall'aspetto pulito con testo che si adatta perfettamente. Ma quando si avvia lo sviluppo, può essere difficile ottenere un layout di pagina e scheda che funzioni per il contenuto reale. E quando si visualizza contenuto dinamico da un CMS, può essere impossibile! Anche con limiti di parole o caratteri, spesso non esiste una soluzione che funzioni in modo affidabile su tutti i dispositivi.
Dovremmo sempre sforzarci di creare implementazioni di layout che tollerano un'ampia gamma di lunghezze di contenuto. Ma non è facile! Ho spesso avuto occasione di ricorrere all'uso di dimensioni e posizione fisse, a causa di vincoli di tempo, supporto insufficiente del browser, design di riferimento debole o semplicemente per mia inesperienza.
Nel corso degli anni, ho imparato che un buon processo iterativo e un sano dialogo con il designer possono aiutare molto quando si affrontano questi problemi e spesso è possibile incontrarsi da qualche parte nel mezzo per ottenere un layout robusto con una certa interattività. Ma torniamo al compito da svolgere: si può fare?
Pensare fuori dagli schemi
In effetti, è possibile ridimensionare le carte in base sia al contenuto anteriore che a quello posteriore e non è così difficile come sembra all'inizio. Dobbiamo solo essere metodici e persistenti!
Vincolare il problema
Iniziamo facendo un elenco dei requisiti del nostro layout. Cercare di scrivere esattamente quello che vuoi potrebbe sembrare un lavoro ingrato, ma è un ottimo modo per scoprire i vincoli che possono essere semplificati per risolvere un problema. Diciamo:
- Vogliamo vedere una o più schede rettangolari, disposte in una griglia a colonna singola oa più colonne;
- Vogliamo che le carte si capovolgano al passaggio del mouse o toccano per rivelare un secondo insieme di contenuti sul retro;
- Vogliamo che le carte siano sempre abbastanza grandi da mostrare tutto il loro contenuto davanti e dietro, indipendentemente dalla lunghezza o dallo stile del contenuto; e
- Nel caso di più colonne, idealmente, vogliamo che tutte le carte abbiano le stesse dimensioni in modo che le righe si allineino bene.
Pensando a questi requisiti, possiamo notare un paio di cose che semplificano il problema:
- Se le carte devono essere presentate in una griglia, abbiamo un vincolo sulla loro larghezza, ovvero le loro larghezze sono funzioni della finestra o del contenitore della griglia piuttosto che del loro contenuto;
- Dato che conosciamo la larghezza di una carta (almeno come percentuale del suo genitore), abbiamo risolto per la dimensione orizzontale e abbiamo solo bisogno che l'altezza della carta si espanda per adattarsi al più alto della sua faccia anteriore o posteriore; e
- Se riusciamo a farlo e ogni carta è autodimensionata verticalmente, possiamo usare le
grid-auto-rows
di CSS Grid per rendere tutte le file di carte alte quanto la carta più alta.
Capire il trucco con le carte
Quindi, come autodimensioniamo le carte? Ora abbiamo semplificato il nostro problema, siamo alla portata della soluzione.
Dimentica, per un momento, l'idea di mettere i contenuti sopra altri contenuti e concentrati sul nostro nuovo requisito: un genitore alto quanto il suo bambino più alto. Questo è facile! Usando le colonne, possiamo fare in modo che un genitore si espanda all'altezza del suo figlio più alto. Quindi, dobbiamo solo usare un piccolo gioco di prestigio per allineare i bambini:
- Imposta i bambini in modo che abbiano la stessa larghezza del loro genitore
- Consenti al secondo figlio di traboccare a destra
- Trasformalo verso sinistra nella sua posizione corretta
.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); }
Se questo approccio sembra ovvio, ti assicuro che ho passato molte ore a esaminare alcune idee davvero terribili prima di pensarci. All'inizio, avevo pianificato di stampare una versione duplicata nascosta del testo della faccia posteriore all'interno della faccia anteriore per espandere la carta alla dimensione corretta. E quando ho pensato di usare l'overflow della colonna, originariamente stavo ritagliando la colonna di destra usando overflow:hidden
e trasformandola solo all'ultimo momento quando è iniziato il passaggio del mouse, poiché non mi ero ancora reso conto che potevo mantenerlo trasformato dall'inizio e utilizzare un altro metodo come l' opacity
o backface-visibility
sul retro per attivarlo e disattivarlo secondo necessità.
In altre parole, le soluzioni ovvie sono il risultato di un duro lavoro! Se ti senti come se avessi sbattuto la testa contro la scrivania per ore su un problema di layout, è importante fare un passo indietro e decidere se stai spendendo il tempo del tuo cliente con saggezza: se suggerire di modificare il design e se perseguire la soluzione nel tuo tempo libero come esercizio di apprendimento quando la pressione è diminuita. Ma quando trovi metodi semplici, non sentirti mai stupido perché ci è voluto molto tempo . Ora, esaminiamo la nostra soluzione completa.
.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); }
Ci sono delle avvertenze?
La soluzione funziona bene in generale, con solo alcuni piccoli avvertimenti da tenere a mente:
- Le carte devono essere presenti in un layout a griglia o in un altro contesto in cui le loro larghezze non dipendono dal contenuto.
- Le schede richiedono un contenuto wrapper di qualche tipo (il nostro
card-body
) in modo che l'area al passaggio del mouse non cambi durante le animazioni. Se la carta stessa è animata, vedrai alcuni glitch mentre l'animazione si interrompe e si riavvia rapidamente. - Gli stili come sfondi e box-shadow sono meglio posizionati direttamente sulle facce anteriore e posteriore, poiché gli effetti sulla carta stessa non verranno animati. Fai attenzione allo stile come i box-shadow sul corpo della carta, poiché naturalmente verranno capovolti.
- Le facce anteriore e posteriore delle carte necessitano che la loro proprietà
box-sizing
sia impostata suborder-box
se hanno il proprio riempimento, a causa del requisitomin-width
, altrimenti traboccheranno. - Safari richiede ancora
-webkit-backface-visibility
, nella sua forma con il prefisso del fornitore.
Aggiunta di un po' di polacco
Ora che abbiamo risolto il problema difficile, diamo un'occhiata a un paio di modifiche che possiamo apportare per far funzionare l'intera interazione nel modo più fluido possibile.
Per prima cosa, controlla se le carte si sovrappongono mentre le giri. Ciò dipenderà dal fatto che tu stia utilizzando più colonne, dalla larghezza della grondaia della colonna, dall'orientamento del capovolgimento e dal valore prospettico della carta, ma è probabile che accada. Puoi aumentare la durata dell'animazione per vedere le cose più chiaramente. Quando è in bilico, sembra innaturale che la carta in bilico giri sotto i suoi vicini successivi, quindi dobbiamo metterla sopra usando z-index
. Abbastanza facile, ma attenzione! Dobbiamo attendere il completamento dell'animazione in uscita prima di ripristinare lo z-index
. Inserisci transition-delay
:
.card { transition: z-index; transition-delay: var(--time); z-index: 0; &:hover { transition-delay: 0s; z-index: 1; } }
Quindi, considera la creazione di uno stato attivo per le carte. Di solito provo a fare in modo che carte come queste si colleghino a un luogo rilevante, anche se non specificato dal designer, poiché elementi con effetti al passaggio del mouse come questo si sentono molto toccabili, quindi è bene fornire una destinazione per i lettori che tentano la fortuna. Mi piace una trasformazione di scala breve e sottile, poiché funziona abbastanza bene indipendentemente dal fatto che la seconda metà dell'animazione venga interrotta o meno dal caricamento della pagina di destinazione (mi piacerebbe che i browser completassero le animazioni in volo in modo pulito prima della navigazione, anche se Sono sicuro che sarebbe molto più difficile da implementare nella pratica di quanto sembri).
Questa è anche una grande opportunità per pensare a quanto sia accessibile il contenuto del dorso delle nostre carte. Il nostro markup è conciso e ben ordinato, quindi abbiamo trattato i lettori di schermo e altri casi d'uso che ignorano lo stile, ma per quanto riguarda gli utenti della tastiera? Se intendiamo rendere le carte stesse ancora, riceveranno il focus mentre gli utenti della tastiera schedano la pagina. Riutilizziamo lo stato al passaggio del mouse della scheda come stato di messa a fuoco e il contenuto posteriore apparirà naturalmente durante la navigazione con la tastiera.
.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); } }
Infine, non dimenticare che ora la scheda si ridimensiona automaticamente per adattarsi al suo contenuto, puoi utilizzare praticamente qualsiasi tecnica di allineamento e spaziatura che ti piace all'interno dei contenitori anteriore e posteriore. Usa l'allineamento flessibile per centrare i titoli, aggiungere padding e persino inserire un'altra griglia all'interno della scheda. Questa è la bellezza di buone soluzioni di layout che si adattano al loro contenuto: ridotto accoppiamento tra bambini e genitori e modularità che ti consente di concentrarti su una cosa alla volta.
.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; }
Avvolgendo
Spero che tu possa trovare utile questa tecnica CSS! Perché non provare alcune variazioni sull'animazione, come un effetto di scala o una semplice dissolvenza incrociata? La tecnica non si limita nemmeno al fattore di forma delle carte. Può essere utilizzato ovunque dove la responsabilità del dimensionamento verticale ricade su più di un elemento. Immagina un sito Web di una rivista con fotografie di grandi dimensioni con didascalie sovrapposte: puoi usarlo per ospitare sia immagini con proporzioni alte che testo lungo e dinamico.
Soprattutto, ricorda i vantaggi di dedicare del tempo a riflettere seriamente sull'esistenza di un modo per implementare un design che sembra funzionare solo con dimensioni e posizione fisse. Spesso c'è, e non importa quanto complicato possa sembrare il problema all'inizio, annotare tutti i tuoi requisiti, dedicare un po' di tempo per creare un test case minimo e affrontarlo metodicamente è sempre la soluzione migliore.