Introduzione
Elementi e stili per la creazione di form accessibili e responsivi.
Nella visualizzazione predefinita di un form gli elementi sono distribuiti verticalmente, ma è possibile utilizzare classi aggiuntive per variare questo tipo di layout.
Bootstrap Italia applica automaticamente a tutti i form display: block
e width: 100%
.
Organizzazione dei campi
Per raggruppare correttamente gli elementi di un modulo form è bene utilizzare la classe .form-group
per ogni singolo blocco, in questo modo l’elemento input, l’etichetta, il testo di aiuto opzionale e la messaggistica di validazione otterranno lo stile grafico e le funzionalità per loro predisposte. Si può usare con <fieldset>
, <div>
o qualsiasi altro elemento.
Gli elementi dei campi devono avere la classe .form-control
applicata.
Dimensionamento delle colonne
Strutture più complesse possono essere costruite usando il sistema a griglia, da utilizzare per layout che richiedono più colonne, larghezze diverse e opzioni di allineamento aggiuntive. La classe .row
ne assicura una corretta spaziatura.
Si può scegliere di dare una dimensione ad una colonna, ad esempio dandogli una classe .col-md-6
per ottenere una certo design dal breakpoint md
in su, mentre le restanti .col-md
si divideranno il resto dello spazio.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div>
<div class="row">
<div class="form-group col-md-6">
<label for="formNome">Nome</label>
<input type="text" class="form-control" id="formNome">
</div>
<div class="form-group col-md-6">
<label for="formCognome">Cognome</label>
<input type="text" class="form-control" id="formCognome">
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="Comune">Comune</label>
<input type="text" class="form-control" id="Comune">
</div>
<div class="form-group col-md">
<label for="Provincia">Provincia</label>
<input type="text" class="form-control" id="Provincia">
</div>
<div class="form-group col-md">
<label for="CAP">CAP</label>
<input type="text" class="form-control" id="CAP">
</div>
</div>
</div>
Ecco l’esempio di una struttura più complessa creata con il sistema a griglie.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<div>
<div class="row">
<div class="form-group col-md-6">
<label class="active" for="inputEmail4">Email</label>
<input type="email" class="form-control" id="inputEmail4" placeholder="inserisci il tuo indirizzo email">
</div>
<div class="form-group col-md-6">
<label class="active" for="exampleInputPassword">Password</label>
<input type="password" data-bs-input class="form-control input-password" id="exampleInputPassword" placeholder="inserisci la tua password">
<span class="password-icon" aria-hidden="true">
<svg class="password-icon-visible icon icon-sm"><use href="/dist/svg/sprites.svg#it-password-visible"></use></svg>
<svg class="password-icon-invisible icon icon-sm d-none"><use href="/dist/svg/sprites.svg#it-password-invisible"></use></svg>
</span>
</div>
</div>
<div class="row">
<div class="form-group col">
<label class="active" for="inputAddress">Indirizzo</label>
<input type="text" class="form-control" id="inputAddress" placeholder="Via Roma, 1">
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="inputCity">Comune</label>
<input type="text" class="form-control" id="inputCity">
</div>
<div class="form-group col-md-2">
<label for="inputCAP">CAP</label>
<input type="text" class="form-control" id="inputCAP">
</div>
<div class="form-group col-md-4">
<div class="select-wrapper">
<label for="selectID">Provincia</label>
<select id="selectID">
<option value="Value 1">Opzione 1</option>
<option value="Value 2">Opzione 2</option>
<option value="Value 3">Opzione 3</option>
<option value="Value 4">Opzione 4</option>
<option value="Value 5">Opzione 5</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<div class="toggles">
<label for="toggleEsempio1a">
Label dell'interruttore 1
<input type="checkbox" id="toggleEsempio1a">
<span class="lever"></span>
</label>
</div>
</div>
</div>
<div class="row mt-4">
<div class="form-group col text-center">
<button type="button" class="btn btn-outline-primary">Annulla</button>
<button type="submit" class="btn btn-primary">Conferma</button>
</div>
</div>
</div>
Auto-dimensionamento
L’esempio seguente usa una delle utilità di flexbox per centrare verticalmente dal breakpoint lg
in su il contenuto e cambiando .col
con .col-auto
in modo che le colonne occupino solo lo spazio necessario. In altre parole, la colonna si dimensiona in base al contenuto. È possibile usarlo anche quando sono presenti altre colonne con dimensioni specifiche (es.: col-sm-3
).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="row align-items-center">
<div class="col-12 col-md-6 col-lg-auto mb-3">
<label class="visually-hidden" for="inlineFormInput">Nome</label>
<input type="text" class="form-control" id="inlineFormInput" placeholder="Mario Rossi">
</div>
<div class="col-12 col-md-6 col-lg-auto mb-3">
<label class="visually-hidden" for="inlineFormInputGroup">Username</label>
<div class="input-group">
<span class="input-group-text">@</span>
<input type="text" class="form-control" id="inlineFormInputGroup" placeholder="Username">
</div>
</div>
<div class="col-6 col-md-3 offset-md-6 offset-lg-0 col-lg-auto">
<div class="form-check m-0">
<input class="form-check-input" type="checkbox" id="autoSizingCheck">
<label class="form-check-label" for="autoSizingCheck">
Ricordami
</label>
</div>
</div>
<div class="col-6 col-md-3 col-lg-auto d-flex justify-content-end">
<button type="submit" class="btn btn-primary">Invia</button>
</div>
</div>
Alternative alle etichette nascoste
Le tecnologie assistive come gli screenreader avranno problemi con i tuoi moduli se non includi un’etichetta per ogni input. Per questi moduli in linea, si può nascondere le etichette usando la classe .visually-hidden
. Esistono altri metodi alternativi per fornire un’etichetta per le tecnologie assistive, come l’attributo aria-label
, aria-labelledby
o title
. Se nessuno di questi è presente, le tecnologie assistive possono ricorrere all’uso dell’attributo placeholder
, se presente, ma è sconsigliato.
Disabilitazione di campi
Aggiungi l’attributo booleano disabled
su un input per impedire le interazioni dell’utente e renderlo più chiaro.
1
<input class="form-control" id="disabledInput" type="text" value="Esempio di input disabilitato" aria-label="Label" disabled>
Disabilitazione di un intero form
Aggiungi l’attributo disabled
al <fieldset>
per disabilitare tutti gli elementi del form contenuti.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<div>
<fieldset disabled aria-label="Form disabilitato">
<legend class="mb-4">Esempio di form disabilitato</legend>
<div class="row mt-4">
<div class="col-12 col-md-6">
<div class="form-group">
<label for="disabledFieldsetInput">Input </label>
<input type="text" id="disabledFieldsetInput" class="form-control" value="Input disabilitato">
</div>
</div>
<div class="col-12 col-md-6">
<div class="form-group">
<div class="select-wrapper">
<label for="disabledFieldsetSelect">Select</label>
<select id="disabledFieldsetSelect">
<option value="Value 1">Select disabilitata</option>
<option value="Value 2">Opzione 2</option>
<option value="Value 3">Opzione 3</option>
<option value="Value 4">Opzione 4</option>
<option value="Value 5">Opzione 5</option>
</select>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12 col-md-6">
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="disabledFieldsetCheck1">
<label class="form-check-label" for="disabledFieldsetCheck1">
Check disabilitato 1
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="disabledFieldsetCheck2">
<label class="form-check-label" for="disabledFieldsetCheck2">
Check disabilitato 2
</label>
</div>
</div>
<div class="col-12 col-md-6">
<div class="form-check">
<input name="gruppo1" type="radio" id="disabledFieldsetRadio1" checked>
<label for="disabledFieldsetRadio1">
Radio disabilitato 1
</label>
</div>
<div class="form-check">
<input name="gruppo1" type="radio" id="disabledFieldsetRadio2">
<label for="disabledFieldsetRadio2">
Radio disabilitato 2
</label>
</div>
</div>
</div>
<button class="btn btn-primary mt-3">Pulsante disabilitato</button>
</fieldset>
</div>
Compatibilità Cross-browser
Mentre Bootstrap applicherà questi stili in tutti i browser, Internet Explorer 11 e successivi non supportano completamente l’attributo disabled
nel <fieldset>
. Utilizza codice JavaScript custom per disabilitare il fieldset in questi browser.
Validazione
Per la validazione dei forms è stato utilizzato il plugin Just Validate.
Come funziona
Per il funzionamento e le opzioni disponibili, si consiglia di consultare la documentazione.
Stili personalizzati
I campi che necessitano di validazione acquisiranno all’invio del form le classi CSS definite nello script che attiva il plugin. Nel nostro caso le classi saranno is-invalid
e just-validate-success-field
. I messaggi di errore avranno classe just-validate-error-label
.
Di seguito un esempio di form validato con Just Validate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<form class="needs-validation" id="justValidateForm">
<div class="row mt-4">
<div class="form-group col-md-3">
<label class="active" for="validationCustom01">Nome</label>
<input type="text" class="form-control" id="validationCustom01" value="Mario" required>
</div>
<div class="form-group col-md-3">
<label class="active" for="validationCustom02">Cognome</label>
<input type="text" class="form-control" id="validationCustom02" value="Rossi" required>
</div>
<div class="form-group col-md-3">
<label for="validationCustomUsername">Username</label>
<input type="text" class="form-control" id="validationCustomUsername" required>
</div>
<div class="form-group col-md-3">
<label class="input-number-label active " for="validationAge">Età (minimo 18 anni)</label>
<input type="number" data-bs-input class="form-control" id="validationAge" value="18" min="18" step="1" required>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="validationCustom03">Città</label>
<input type="text" class="form-control" id="validationCustom03" required>
</div>
<div class="form-group col-md-3">
<label for="validationCustom04">Provincia</label>
<input type="text" class="form-control" id="validationCustom04" required>
</div>
<div class="form-group col-md-3">
<label for="validationCustom05">CAP (5 cifre)</label>
<input type="text" class="form-control" id="validationCustom05" required>
</div>
</div>
<div class="row align-items-center">
<div class="col-md-9 col-lg-6">
<div class="form-check mt-0">
<input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>
<label class="form-check-label" for="invalidCheck">Accetto i termini e le condizioni.</label>
</div>
</div>
<div class="col-md-3 col-lg-6 mt-3 mt-md-0 d-flex justify-content-center justify-content-md-end justify-content-lg-start">
<button class="btn btn-primary" type="submit">Invia</button>
</div>
</div>
</form>
<div class="row mt-4">
<div class="col-12">
<div aria-live="polite" id="errorMsgContainer"></div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const errorMessage = '<div class="alert alert-danger alert-dismissible fade show" role="alert"><strong>Attenzione</strong> Alcuni campi inseriti sono da controllare.<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi avviso">';
const errorWrapper = document.querySelector('#errorMsgContainer');
const validate = new bootstrap.FormValidate('#justValidateForm', {
errorFieldCssClass: 'is-invalid',
errorLabelCssClass: 'form-feedback',
errorLabelStyle: '',
focusInvalidField: false,
})
validate
.addField('#validationCustom01', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.addField('#validationCustom02', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.addField('#validationCustom03', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.addField('#validationCustom04', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.addField('#validationCustomUsername', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.addField('#validationAge', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
{
rule: 'minNumber',
value: 18,
errorMessage: 'Deve essere maggiore di 17'
},
])
.addField('#validationCustom05', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
{
rule: 'minLength',
value: 5,
errorMessage: 'Inserire 5 cifre'
},
{
rule: 'maxLength',
value: 5,
errorMessage: 'Inserire 5 cifre'
},
{
rule: 'number',
errorMessage: 'Inserire un numero'
},
])
.addField('#invalidCheck', [
{
rule: 'required',
errorMessage: 'Questo campo è richiesto'
},
])
.onSuccess(() => {
document.forms['justValidateForm'].submit()
})
.onFail((fields) => {
errorWrapper.innerHTML = '';
errorWrapper.innerHTML = errorMessage
})
})
</script>
Continua la lettura
I singoli campi di tipo input, checkbox, radio, toggle, ecc. sono trattati in pagine separate della documentazione, continua a leggere alla pagina dedicata ai campi di input.