Siamo indecisi su quale componente esterno usare per aggiungere uno slideshow del nostro sito responsive? Vogliamo approfondire le potenzialità offerte da flexbox? Abbiamo almeno due valide ragioni per lavorare al progetto che stiamo per esaminare.
È vero che ci sono molti tipi di slideshow disponibili come widget di famosi frameworks di UI, tuttavia se non abbiamo bisogno di features particolari possiamo realizzarne uno piuttosto rapidamente sfruttando flexbox e poche righe di JavaScript.
In questo modo evitiamo di:
- importare il codice necessario aumentando il peso della pagina;
- investire tempo (anche minimo) nella comprensione di come utilizzare il plugin;
- avere un controllo ridotto sul comportamento;
- avere molto più di quanto ci si serve in termini di features, classi e codice in generale;
- dover ricorrere probabilmente a sovrascritture o modifiche per la customizzazione.
Slideshow... sì ma come?
Tra i tanti tipi di slideshow, scegliamo uno dei più classici ed efficaci: la galleria con immagini che si alternano con transizioni in fade e una dot navigation ( menu "a pallini") posizionata sopra la slide.
Gestiremo il funzionamento dello slideshow interamente con i fogli di stile utilizzando una classe “active” sul pallino di navigazione e sulla slide selezionata per mostrarla. JavaScript si occuperà solo di assegnare e rimuovere la classe. Sfrutteremo flexbox per fare le slides e la navigazione.
Il flexbox layout è utilissimo per la realizzazione di componenti con elementi che vanno allineati piuttosto che per layout di pagina, a causa del minore controllo che ci mette a disposizione.
Con flexbox possiamo infatti ovviare ai limiti dei display ad orientamento monodirezionale (verticale con il display block, orizzontale con il display inline). Piuttosto dell'esatta posizione degli elementi al pixel viene data priorità alla loro distribuzione all'interno di un determinato spazio, definito dal flex container.
In uno scenario di compatibilità con i dispositivi mobili senza alcuna risoluzione di riferimento i pixel sono un'informazione sempre più marginale ed è necessario un approccio mobile-first. Flexbox ci aiuta proprio nell'implementazione del nostro design responsivo.
Il markup HTML dello slideshow
Come primo step, creiamo la struttura HTML del nel nostro slideshow. Per simulare in maniera realistica il risultato finale, lo creeremo all'interno di un div container responsive con larghezza in percentuale ed una max-width
per desktop.
Inseriamo un div container dedicato allo slideshow che contiene una lista con le slides e una lista con i pallini per la navigazione. Dentro la lista delle slides mettiamo come primo item un'immagine placeholder, che serve per determinare l'ingombro totale della slide.
NOTA: L'immagine del placeholder così come tutte le immagini dello slideshow devono avere la stessa aspect ratio (16:9, 4:3, ecc…).
<div class="container">
<h1>Flexbox Slideshow</h1>
<div class="flexbox-slideshow">
<ul class="slideshow">
<li class="placeholder">
<img src="https://www.html.it/wp-content/uploads/2016/10/slide_flexbox_placeholder.jpg">
</li>
<li class="slide active" id="slide-1"><!-- ... --></li>
<li class="slide" id="slide-2"><!-- ... --></li>
<li class="slide" id="slide-3"><!-- ... --></li>
<li class="slide" id="slide-4"><!-- ... --></li>
<li class="slide" id="slide-5"><!-- ... --></li>
</ul>
<ul class="dotnav">
<li class="dotnav-item active" onclick="changeOrder(this, 1)"><span></span></li>
<li class="dotnav-item" onclick="changeOrder(this, 2)"><span></span></li>
<li class="dotnav-item" onclick="changeOrder(this, 3)"><span></span></li>
<li class="dotnav-item" onclick="changeOrder(this, 4)"><span></span></li>
<li class="dotnav-item" onclick="changeOrder(this, 5)"><span></span></li>
</ul>
</div>
</div>
Ogni slide contiene un'immagine e 2 caption, uno per il titolo della foto l'altro per l'autore. Alla prima slide e al primo pallino impostiamo la classe active
.
<li class="slide active" id="slide-1">
<img src="https://www.html.it/wp-content/uploads/2016/10/slide_flexbox_moon-1.jpg">
<div class="caption-container">
<div class="caption caption-title">
<h2>Great caption about the moonlight</h2>
</div>
<div class="caption caption-author">
<span class="author">John Doe</span>
</div>
</div>
</li>
CSS, struttura slideshow
Abbiamo scelto come transizione il fade e quindi le slides <li>
sono posizionate una sopra all'altra con posizione assoluta rispetto alla lista <ul>
che deve avere position relative dichiarata.
L'elemento della lista che contiene il placeholder è l'unico con position static
di default e resterà sempre sotto le slides. Per mostrare la slide attiva con la classe aggiuntiva “active” cambieremo lo z-index mentre per l'effetto fade con le CSS transitions cambieremo l'opacità della sua immagine. Le immagini diventano responsive impostando la larghezza al 100%.
.flexbox-slideshow {
position: relative;
overflow: hidden;
}
.slideshow {
padding: 0;
margin: 0;
list-style: none;
}
.slideshow li:not(.placeholder) {
position: absolute;
z-index: 1;
top: 0;
left: 0;
}
.slideshow li img {
width: 100%;
max-width: 100%;
display: block;
opacity: 0;
}
.slideshow li.active {
z-index: 2;
}
.slideshow li.active img {
opacity: 1;
}
CSS flexbox, le slides
Con flexbox vogliamo gestire i due caption dell'immagine in maniera veloce, senza doverli posizionare gestendo pixel e margini. Li vogliamo centrare verticalmente rispetto all'immagine ed allinearli alla sua sinistra, in modo tale da poterli animare in ingresso ed in uscita. Vogliamo inoltre distribuirli in maniera uniforme nello spazio disponibile. Inoltre i due caption contengono dei testi che in un sito responsive, a seconda della risoluzione, possono diventare multilinea ed avere quindi un ingombro diverso.
Come sappiamo, allineare verticalmente gli elementi non è mai stato immediato con i CSS ma con flexbox è facilissimo. Innanzitutto gestiamo la grandezza del container dei caption in modo tale che occupi lo stesso spazio dell'immagine e poi facciamolo diventare un flex container scrivendo display: flex
. Ora tutti i nodi figli diretti sono flex-items, nel nostro caso il caption del titolo e il caption dell'autore.
Con le altre proprietà del div .caption-container
stabiliamo come allineare i suoi flex-items. Poiché vogliamo che il caption dell'autore sia sotto quello del titolo scriviamo
flex-direction: column
per indicare che la direzione (asse principale) su cui si disporranno i flex-items è verticale. Con:
justify-content: center
diciamo al flex-container di disporre i flex-items al centro del suo asse principale permettendoci quindi di centrarli verticalmente. Infine:
align-items: flex-start
allinea i flex-items all'inizio dell'asse secondario o meglio trasversale (quindi nel nostro caso orizzontale) cioè a sinistra.
A questo punto possiamo animare i caption etichettati con la classe active
(+ CSS transitions) cambiando il loro margine sinistro per farle entrare ed uscire sull'immagine attiva.
.slideshow li .caption-container {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: flex-start;
flex-wrap: wrap;
flex-direction: column;
}
.slideshow li .caption {
background: rgba(0, 0, 0, 0.5);
color: #f2f2f2;
padding: 10px 20px;
margin-left: -100%;
}
.slideshow li .caption.caption-title {
margin-bottom: 10px;
transition: all .2s ease;
}
.slideshow li .caption.caption-title > * {
margin: 0;
}
.slideshow li.active .caption {
margin-left: 0;
}
È importante notare come usando flexbox non dobbiamo dare altezze, larghezze in pixel, margini, posizionamenti puntuali e questo è perfetto per lo sviluppo responsive.
CSS flexbox, menu di navigazione a pallini
Per gestire il menu di navigazione usiamo lo stesso approccio facendo diventare la lista <ul>
.dotnav
un flex-container con display: flex
ed allineando i flex-items cioè i pallini in basso al centro della slide impostando justify-content: center
e align-items: flex-end
.
In questo caso non impostiamo la flex-direction
perché usiamo quella di default che è row
. Justify-content
lavora sull'asse principale, quindi impostare il valore center centra gli elementi in orizzontale se la flex-direction
è row
(default) e in verticale se la flex-direction
è column
(come nel caso precedente del .caption-container
). Stesso discorso per la proprietà align-items
solo applicato all'asse trasversale. Sempre con la classe active
stiliamo il pallino relativo alla slide attiva.
.dotnav {
position: absolute;
list-style: none;
padding: 20px;
margin: 0;
top: 0;
width: 100%;
z-index: 100;
display: flex;
justify-content: center;
align-items: flex-end;
flex-wrap: wrap;
height: 100%;
}
.dotnav li span {
border-radius: 50%;
display: block;
height: 20px;
width: 20px;
margin-right: 20px;
background: rgba(255, 255, 255, 0.3);
cursor: pointer;
box-shadow: 0px 1px 6px #000;
}
.dotnav li.active span {
background: rgba(255, 255, 255, 0.5);
cursor: default;
}
.dotnav li:last-child span {
margin-right: 0;
}
CSS, ottimizzazione dello slideshow per mobile
Il nostro design è già responsivo grazie all'utilizzo di percentuali e di flexbox, ma possiamo curare i dettagli migliorando il risultato su schermi inferiori a 600px utilizzando una media query.
In particolare, su mobile possiamo nascondere il caption dell'autore e cambiare l'allineamento del caption del titolo per evitare che copra l'intera foto. Lo possiamo allineare in alto impostando justify-content: flex-start
e cambiare l'animazione usando il margin-top
e resettando il margin-left
.
@media screen and (max-width: 599px) {
body {
background: black;
}
h1 {
margin-bottom: 0;
}
.container {
margin-top: 20px;
padding: 10px;
}
.slideshow li .caption-container {
justify-content: flex-start;
}
.slideshow li .caption {
font-size: 3vw;
width: 100%;
margin-left: 0;
margin-top: -100%;
text-align: center;
}
.slideshow li .caption.caption-author {
display: none;
}
.slideshow li.active .caption {
margin-top: 0%;
}
.dotnav {
padding: 3vw;
}
.dotnav li span {
height: 3.5vw;
width: 3.5vw;
margin-right: 10px;
}
}
Come farlo funzionare
Ora per farlo funzionare è sufficiente creare una funzione JavaScript che all'evento click sul pallino di navigazione assegni la classe active
a se stesso e alla relativa slide. È importante rimuovere la classe active
su tutti gli altri item prima di impostarla nuovamente.
Ecco un esempio di codice (JavaScript puro) per attivare la UI:
<script type="text/javascript">
function changeOrder(dot, number) {
var slides = document.querySelectorAll(".slide");
var dots = document.querySelectorAll(".dotnav-item");
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('active');
dots[i].classList.remove('active');
}
var elemName = "slide-" + number;
var elem = document.getElementById(elemName);
elem.classList.add('active');
dot.classList.add('active');
}
</script>
Credit immagini Alphacoders.com