The HTML structure of forms in SPIP

Data entry forms used in the private zone

A reference document detailing how forms in SPIP should be structured

HTML structure

A basic form is structured as follows:

<div class="formulaire_spip formulaire_editer formulaire_editer_nomformulaire" id="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>

The surrounding div is assigned the generic class formulaire_spip. Data entry forms in the private zone are additionally assigned the class formulaire_editer, indicating that we’re dealing with a database data entry form.

Each input field is encapsulated in a .editer class element, which must be grouped in a class element .editer-groupe. Until SPIP 3.0 these classes were respectively carried by html tags li et ul. From SPIP 3.1 onwards, the convention is to use simple div to reduce the verbosity of the voice synthesis and improve the accessibility of forms.

The first fieldset being optional, we could also code it without the fieldset and without the optional paragraphs:

<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>

The special classes

  • "explication": to indicate an explanatory message (which applies either to all of the fields, or to just one step). Example: <p class="explication">.
  • "attention": to display a message concerning a essential entry field. Example: <em class="attention"><:text_login_warning:></em>.
  • "obligatoire": to indicate a compulsory field to be applied to the parent list element. Example: <li class="obligatoire">.
  • "erreur": to indicate a step causing an error, to be applied to the parent list element. Example: <li class="erreur">. Each error uses an explanatory message tagged with the class "erreur_message": <span class="erreur_message">.

The embracing frame

This form may optionally be included within a cadre-formulaire-editer (entry form frame), and can also therefore contain a entete-formulaire (form header):

<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>

Managing the success/error messages

Global messages

A form must include two paragraphs to show the global success and error messages which may arise after submitting the form. The environment variables message_ok and message_erreur are the parameters returned by SPIP (using the CVT forms).

<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>

Special messages

Each field on the form, wrapped within an li, can receive a special error message. This is contained in the ’erreurs’ environment table array and can be retrieved as follows:

[(#ENV**{erreurs}|table_valeur{field_name})]

We can assign the ’erreur’ class to .editer and display a special error if there is one as shown below:

<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>

Particularities for CSS styling

Input fields

Each <input /> that is not hidden must have a class identical to its type (in order to remediate a deficiency in Internet Explorer):

<input type="text" class="text" name="titre" id="titre" value="[(#ENV**{titre})]" />

Submit buttons

The submit buttons are included in a .boutons box (which can accept several buttons):

<p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>

radio/checkbox

In the case of radio buttons or checkboxes, we may not use the same structure, for example to have the button before the label, or to have radio buttons displayed horizontally.

Each (radio + label) entry may therefore be framed within a .choix block:

<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>

By default, the list is displayed vertically. To make the list horizontal, you only need to specify that the .champ (field) in question is an inline type:

.formulaire_editer .editer_syndication .choix {display:inline;}

The general principles for these forms to have labels left-aligned.

Suppose we find ourselves with this scenario:

<div class="editer-groupe">
	<div class="editer">
		<label />
		<input />
	</div>
	<div class="editer">
		<label />
		<em />
		<span />
		<input />
	</div>	
</div>

1) We apply a left padding to the first LI equal to the width of the label (e.g. 120px)

.formulaire_spip .editer {
	margin: 0;
	padding: 10px 10px 10px 130px;
	clear:both;
	border-top: 1px solid #eee;
}

2) We ask that the label be floating and displaced to the left (using a negative margin)

.formulaire_spip .editer label {
	width: 120px;
	float:left;
	margin-left:-125px; 
	text-align: left;
	vertical-align: top;
}

3) Whenever a fieldset follows an LI, we also displace it to the left
(only IE doesn’t recognise this) so that the fieldset also fills up the width

.formulaire_spip .editer fieldset {
	border:1px solid #888;
	background:white;
	margin-left:-125px; /* displace to the left... IE < 8 does not understand this */
}

Author Mark Published : Updated : 06/07/23

Translations : català, English, Español, français, Nederlands