Carte Magic Flip: Risolvere un problema di dimensionamento comune

Pubblicato: 2022-03-10
Riassunto rapido ↬ In questo articolo, Dan Halliday passa in rassegna l'approccio standard alla creazione di carte a fogli mobili animate e introduce un metodo migliorato che risolve il suo problema di dimensionamento.

Quali 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.
Altro dopo il salto! Continua a leggere sotto ↓

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

Un'implementazione standard di flip card che utilizza il posizionamento assoluto (vedi la penna "[Magic Flip Cards 1: The Standard Implementation](https://codepen.io/smashingmag/pen/JjdPJvo)" di Dan Halliday)

Un'implementazione standard di flip card che utilizza il posizionamento assoluto (vedi la penna "Magic Flip Cards 1: The Standard Implementation" di Dan Halliday)

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.

In che modo l'implementazione della scheda flip standard non riesce con contenuti posteriori più lunghi
Questo è il modo in cui l'implementazione della scheda flip standard fallisce con contenuti posteriori più lunghi. (Grande anteprima)

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.

Come fallisce l'implementazione delle carte flip standard con contenuti posteriori più lunghi (vedi la penna "[Magic Flip Cards 2: How Absolute Positioning Fails](https://codepen.io/smashingmag/pen/QWbLMLz)" di Dan Halliday)

Come fallisce l'implementazione delle carte flip standard con un contenuto posteriore più lungo (vedi la penna "Magic Flip Cards 2: How Absolute Positioning Fails" di Dan Halliday)

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:

  1. Imposta i bambini in modo che abbiano la stessa larghezza del loro genitore
  2. Consenti al secondo figlio di traboccare a destra
  3. 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); } 

Dimensionamento verticale mediante overflow orizzontale fisso (vedi la penna "[Magic Flip Cards 3: Vertical Sizing by Fixed Horizontal Overflow](https://codepen.io/smashingmag/pen/ExjYvjP)" di Dan Halliday)

Dimensionamento verticale per overflow orizzontale fisso (vedi la penna "Magic Flip Cards 3: Dimensionamento verticale per overflow orizzontale fisso" di Dan Halliday)

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

La soluzione completa delle carte magiche flip (vedi la penna "[Magic Flip Cards 4: The Complete Solution](https://codepen.io/smashingmag/pen/xxGKLZO)" di Dan Halliday)

La soluzione completa delle carte magiche flip (vedi la penna "Magic Flip Cards 4: La soluzione completa" di Dan Halliday)

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 su border-box se hanno il proprio riempimento, a causa del requisito min-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.