Abbiamo visto nella precedente sezione dedicata al layout a griglia come flexbox trovi possibilità di applicazione sia a livello del layout generale della pagina, sia per il layout di singoli componenti. Rientra in questo secondo scenario la possibilità di adoperarlo per strutturare il layout dei form.
Il caso da manuale è quello di componenti di un form da disporre orizzontalmente, l'uno accanto all'altro, una label affiancata da un campo di testo, ma anche l'abbinata pulsante più input. In entrambi i casi possiamo sfruttare flexbox sia per affiancare facilmente i componenti senza fare ricorso ai float, sia per creare campi di input che si estendano automaticamente per tutta la larghezza del contenitore, cosa che ci libera dalla necessità di dover impostare una dimensione fissa o in percentuale.
Nella demo 14, all'interno di uno dei box della griglia, abbiamo inserito un bottone affiancato da un campo di testo. Il bottone assumerà la larghezza data dal suo contenuto, il campo di testo si estenderà fino a occupare tutto lo spazio disponibile rimanente. Giunti a questo punto nella lettura, dovrebbero essere chiari i meccanismi con cui ottenere il risultato.
Pulsante e campo di testo sono inseriti in un elemento contenitore:
<div class="flex-form-container">
<button class="btn btn-primary flex-form-btn">Invia</button>
<input type="text" id="nome" class="flex-form-input">
</div>
Per affiancare i due elementi basta rendere flessibile il contenitore e indicare la direzione su row
:
.flex-form-container {
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
}
Per il pulsante, dal momento che la larghezza sarà quella dettata dal suo contenuto, impostiamo solo un margine destro per separarlo dal campo:
.flex-form-btn {margin-right: 10px;}
Per far sì che il campo di testo occupi tutto lo spazio disponibile specifichiamo una flex-grow
pari a 1
con la proprietà abbreviata flex
:
.flex-form-input {
flex: 1;
-webkit-flex: 1;
}
Per apprezzare la robustezza e la flessibilità di questa soluzione, provate a restringere e allargare la finestra del browser: verificherete come il modulo si adatti sempre alla larghezza del contenitore rimanendo immutata la capacità del campo di testo di occupare lo spazio disponibile.
A partire da questo caso molto semplificato, possiamo spingerci in avanti per realizzare un layout più complesso, come nella demo 15.
Nel form le label, di lunghezza variabile, saranno allineate a sinistra; accanto ad esse, i campi di testo saranno perfettamente allineati, occupando tutto lo spazio disponibile in larghezza; il pulsante sarà allineato con i campi di testo.
Questo il markup HTML:
<form class="flex-form">
<div class="flex-form-container">
<label for="nome" class="flex-form-label">Nome:</label>
<input type="text" id="nome" class="flex-form-input">
</div>
<div class="flex-form-container">
<label for="cognome" class="flex-form-label">Cognome:</label>
<input type="text" id="cognome" class="flex-form-input">
</div>
<div class="flex-form-container">
<label for="email" class="flex-form-label">Indirizzo email:</label>
<input type="text" id="email" class="flex-form-input">
</div>
<div class="flex-form-container">
<button class="btn btn-primary form-flex-button">Invia</button>
</div>
</form>
Dovendo operare con flexbox emerge chiaramente la modalità di implementazione da adottare. Ci muoviamo in due direzioni, come chiarisce questa schermata:
Rispetto al contenitore rappresentato dal form ci muoviamo in senso verticale, dall'alto in basso, con 4 righe sovrapposte. Per il form con classe .flex-form
, dunque, dichiareremo la proprietà display: flex
e imposteremo la direzione su column
:
.flex-form {
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
}
Ciascuna riga comprende poi i componenti del modulo, ovvero label, campi di testo e un pulsante. In questo caso ci muoviamo in senso orizzontale. Dichiareremo sempre flex il contenitore, ma la direzione sarà row
:
.flex-form-container {
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
}
Il punto chiave per realizzare il layout così come mostrato negli screenshot è la label. Ad essa dobbiamo assegnare una larghezza fissa. è l'unico modo che abbiamo per allineare il pulsante della quarta riga ai campi di testo. Lo allineeremo infatti assegnandogli un margin sinistro pari alla larghezza della label e aggiungendo il valore del suo margine destro. Ecco la regola per la label:
.flex-form-label {
width: 100px;
font-weight: bold;
text-align: left;
margin-right: 5px;
}
E quella per il pulsante:
.form-flex-button {margin-left: 105px;}
Per i campi di testo vale quanto vista in precedenza nel primo esempio:
.flex-form-input {
flex: 1;
-webkit-flex: 1;
border: 1px solid #333;
border-radius: 3px;
}
Provate anche in questo caso ad allargare e restringere la finestra del browser per verificare la validità della tecnica e l'adattabilità del form. Confrontate anche con il modulo contenuto nel terzo box, che è stato realizzato con i float, senza flexbox. I problemi sono evidenti. Se a prima vista è tutto regolare, provando a restringere la larghezza, il layout del form con i float si rompe:
E quando invece il box cresce in larghezza non si rispetta la specifica per cui il campo di testo deve occupare automaticamente tutto lo spazio disponibile:
Il problema con il form creato con i float è dato dall'impossibilità, in questa configurazione di markup, di assegnare una larghezza del 100% con cui si estenderebbe a occupare tutto lo spazio disponibile.
La soluzione ovviamente c'è e l'abbiamo applicata nella demo 16. In queste situazioni basta racchiudere il campo di testo in un div e assegnargli a quel punto la larghezza massima:
<div class="form-input-container">
<input type="text" id="email" class="float-form-input">
</div>
.float-form-input {
width: 100%;
display: block;
border: 1px solid #333;
border-radius: 3px;
}
Un vantaggio rimane per la soluzione con flexbox. Nel parte con la label più lunga ('Indirizzo email'), che abbiamo messo appositamente, la label stessa si dispone su due righe aumentando in altezza, ma per le caratteristiche del flexbox e per via del valore stretch
che rende le colonne di altezza uguale, il campo di testo si adegua all'altezza della label, rendendo il layout generale più armonico e bilanciato.