Structure HTML
Un formulaire de base est ainsi structuré :
<div class="formulaire_spip formulaire_editer formulaire_editer_nomformulaire formulaire_editer_nomformulaire-id">
<a id="nomformulaire" name="nomformulaire"></a>
<form action="#" method="post">
<fieldset>
<legend>Une légende</legend>
<p class="explication">Un texte d'explication</p>
<div class="editer-groupe">
<div class="editer editer_nomlabel obligatoire erreur">
<label for="nomlabel">Courriel</label>
<em class="aide">#AIDER{arttitre}</em>
<p class="explication"> Explication du label</p>
<span class="erreur_message">Message d'erreur</span>
<input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
</div>
</div>
</fieldset>
</form>
</div>
Le div englobant porte la classe générique formulaire_spip
. Les formulaires d’édition de l’espace privé portent de plus la classe formulaire_editer
indiquant qu’on a affaire à un formulaire d’édition de données d’une base.
Chaque champ de saisie est encapsulé dans un élément de classe .editer
, qui doivent être regroupés dans un élement de classe .editer-groupe
. Jusqu’à SPIP 3.0 ces classes étaient portées respectivement par des balises html li
et ul
. A partir de SPIP 3.1 on prend pour convention d’utiliser de simples div
pour réduire la verbosité de la synthèse vocale et améliorer l’accessibilité des formulaires.
Le premier fieldset étant optionnel, on peut aussi écrire, sans le fieldset et sans les paragraphes optionnels :
<div class="formulaire_spip formulaire_editer formulaire_editer_nomformulaire formulaire_editer_nomformulaire-id">
<a id="nomformulaire" name="nomformulaire"></a>
<form action="#" method="post">
<div class="editer-groupe">
<div class="editer editer_nomlabel obligatoire">
<label for="nomlabel">Courriel</label>
<input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
</div>
</div>
</form>
</div>
Les classes spéciales
- «
explication
» : pour indiquer un message d’explication (qui porte soit pour l’ensemble des champs, soit sur une étape). Exemple :<p class="explication">
. - «
attention
» : pour afficher un message concernant un champ d’édition critique. Exemple :<em class="attention"><:texte_login_precaution:></em>
. - «
obligatoire
» : pour signaler un champ obligatoire, à appliquer à l’élément de liste parent. Exemple :<div class="obligatoire">
. - «
erreur
» : pour signaler une étape en erreur, à appliquer à l’élément de liste parent. Exemple :<div class="erreur">
. chaque erreur bénéficie d’un message explicatif, portant la class «erreur_message
» :<span class="erreur_message">
.
Cadre englobant
Ce formulaire peut optionnellement être inclus dans un cadre-formulaire-editer, et peut alors contenir un entete-formulaire :
<div class="cadre-formulaire-editer">
<div class="entete-formulaire"></div>
<div class="formulaire_editer formulaire_editer_site formulaire_editer_site-#ENV{id_site,nouveau}"></div>
</div>
Gestion des messages réussite/erreur
Messages globaux
Un formulaire comporte obligatoirement deux paragraphes permettant d’afficher les réussites et erreurs globales qui ont pu apparaître à la soumission. Les variables d’environnements message_ok
et message_erreur
sont des retours envoyés par SPIP (formulaires CVT).
<div class="formulaire_editer formulaire_editer_site formulaire_editer_site-#ENV{id_site,nouveau}">
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
</div>
Messages spécifiques
Chaque champ de formulaire, encapsulé dans un .editer
peut recevoir un message d’erreur spécifique. Celui-ci est contenu dans le tableau d’environnement ’erreurs’ et peut être obtenu de la sorte :
[(#ENV**{erreurs}|table_valeur{nom_du_champ})]
On peut attribuer la classe ’erreur’ à .editer
et afficher une erreur spécifique si elle existe de la sorte :
<div class="editer editer_descriptif[ (#ENV**{erreurs}|table_valeur{descriptif}|oui)erreur]">
<label for="descriptif"><:texte_descriptif_rapide:></label>
[<span class='erreur_message'>(#ENV**{erreurs}|table_valeur{desctiptif})</span>]
<textarea name='descriptif' id='descriptif' rows='2' cols='40'>[(#ENV**{descriptif})]</textarea>
</div>
Particularités pour les styles css
Champs input
Chaque <input />
différent de hidden
doit posséder une classe identique à son type (afin de palier à un déficience du navigateur Internet Explorer) :
<input type="text" class="text" name="titre" id="titre" value="[(#ENV**{titre})]" />
Boutons de soumission
Les boutons de soumissions sont inclus dans une boîte .boutons
(qui peut recevoir plusieurs boutons) :
<p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
radio/checkbox
Dans le cas de bouton radio ou checkbox, on peut ne pas reprendre tout a fait la même structure, par exemple pour avoir le bouton avant le label, ou pour avoir la liste radio en horizontal.
Chaque entrée (radio + label) peut alors être encadrée par un bloc .choix
<div class="editer editer_syndication">
<div class="choix">
<input type='radio' class="radio" name='syndication' value='non' id='syndication_non'[ (#ENV{syndication}|=={non}|?{'checked="checked"'})] />
<label for='syndication_non'><:bouton_radio_non_syndication:></label>
</div>
<div class="choix">
<input type='radio' class="radio" name='syndication' value='oui' id='syndication_oui'[ (#ENV{syndication}|=={oui}|?{'checked="checked"'})] />
<label for='syndication_oui'><:bouton_radio_syndication:><em>#AIDER{rubsyn}</em></label>
</div>
</div>
Par défaut, la liste est verticale. Pour rendre la liste horizontale,
il suffit de spécifier que .champ en question est de type inline :
.formulaire_editer .editer_syndication .choix {display:inline;}