Estrutura HTML
Um formulário básico é estruturado como abaixo:
<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>Uma legenda</legend>
    <p class="explication">Um texto explicativo</p>
    <div class="editer-groupe">
      <div class="editer editer_nomlabel obligatoire erreur">
        <label for="nomlabel">E-mail</label>
        <em class="aide">#AIDER{arttitre}</em>
        <p class="explication">Explicação do label</p>
        <span class="erreur_message">Mensagem de erro</span>
        <input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
      </div>
    </div>
  </fieldset>
</form>
</div>
A div envolvente possui a classe genérica formulaire_spip. Os formulários de edição da área restrita possuem ainda a classe formulaire_editer que trata-se de um formulário de edição de dados de uma base.
Cada campo de entrada fica envolvido num elemento com a classe .editer, que deve ser agrupado num elemento com a classe .editer-groupe. Até o SPIP 3.0 essas classes eram atribuídas respectivamente às tags HTML li e ul. A partir do SPIP 3.1 convencionou-se usar div simples para reduzir a verbosidade da síntese vocal e melhorar a acessibilidade dos formulários.
O primeiro fieldset sendo opcional, pode-se também escrever, sem o fieldset e sem os parágrafos opcionais:
<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">E-mail</label>
      <input type="type" class="type" name="nomlabel" id="nomlabel" value="" />
    </div>
  </div>
</form>
</div>
As classes especiais
-  «
explication»: para indicar uma mensagem explicativa (que se aplica ao conjunto de campos, ou a uma etapa). Exemplo:<p class="explication">. -  «
attention»: para exibir uma mensagem relativa a um campo de edição crítico. Exemplo:<em class="attention"><:texte_login_precaution:></em>. -  «
obligatoire»: para indicar um campo obrigatório, a ser aplicada ao elemento superior. Exemplo:<div class="obligatoire">. -  «
erreur»: para indicar uma etapa com erro, a ser aplicada ao elemento superior. Exemplo:<div class="erreur">. Cada erro inclui uma mensagem explicativa, que usa a classe «erreur_message»:<span class="erreur_message">. 
Moldura envolvente
Opcionalmente, este formulário pode ser inserido num cadre-formulaire-editer, e pode então conter um cabeçalho de formulário:
<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>
Gestão das mensagens de sucesso/erro
Mensagens globais
Um formulário comporta obrigatoriamente dois parágrafos que permitem exibir os sucessos e erros globais que possam ocorrer na submissão. As variáveis de ambiente message_ok e message_erreur são os retornos enviados pelo SPIP (formulários CVT).
<div class="formulaire_editer formulaire_editer_site formulaire_editer_site-#ENV{id_site,nouveau}">
  [<div class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</div>]
  [<div class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</div>]
</div>
Mensagens específicas
Cada campo de formulário, envolvido num .editer pode receber uma mensagem de erro específica. Esta está contida na matriz de ambiente ’erreurs’ e pode ser obtida do seguinte modo:
[(#ENV**{erreurs}|table_valeur{nom_du_champ})]
Pode-se atribuir a classe ’erreur’ a .editer e exibir um erro específico, se existir, como a seguir:
<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>
Particularidades para os estilos CSS
Campos input
Cada <input /> diferente de hidden deve possuir uma classe idêntica ao seu tipo (para remediar uma deficiência do navegador Internet Explorer) :
<input type="text" class="text" name="titre" id="titre" value="[(#ENV**{titre})]" />
Botões de submissão
Os botões de submissão estão contidos numa caixa .boutons (que pode receber vários botões):
<p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
radio/checkbox
No caso de botão rádio ou checkbox, Pode não ser necessário manter exatamente a mesma estrutura, por exemplo, para colocar o botão antes do label ou para exibir a lista de opções rádio na horizontal.
Cada entrada (radio + label) pode ser envolvida por um bloco .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>
Por padrão, a lista é vertical. Para tornar a lista horizontal, basta especificar que o .champ em questão é do tipo inline:
.formulaire_editer .editer_syndication .choix {display:inline;}