#Écrire une section
Une section est un fichier de sections/ : du balisage, et à la fin un
{% schema %} qui déclare ce qui est modifiable. C’est l’unité dont on
compose une page — un bandeau d’accueil, une grille de prestations, un
formulaire de contact — et c’est là que se passe l’essentiel du travail d’un
thème.
Cette page montre comment on en écrit une, ce qu’elle reçoit au rendu, et les deux manières dont elle peut être appelée.
#Un exemple complet
Celui-ci est réel : c’est themes/origo/sections/prestations.liquid, réduit
de moitié pour tenir sur un écran, mais rien n’y a été inventé.
<section class="section section-{{ section.settings.fond | default: 'papier' }} prestations" id="prestations">
<div class="enveloppe">
<div class="tete">
{%- if section.settings.surtitre != blank -%}
<span class="surtitre">{{ section.settings.surtitre }}</span>
{%- endif -%}
{%- if section.settings.titre != blank -%}
<h2 class="titre titre-section">{{ section.settings.titre }}</h2>
{%- endif -%}
</div>
<div class="grille grille-{{ section.settings.colonnes | default: '3' }}">
{%- for bloc in section.blocks -%}
<article class="carte">
<h3>{{ bloc.settings.nom }}</h3>
{%- if bloc.settings.description != blank -%}
<p>{{ bloc.settings.description }}</p>
{%- endif -%}
{%- if bloc.settings.prix != blank -%}
<span class="prix">{{ bloc.settings.prix }}</span>
{%- endif -%}
</article>
{%- endfor -%}
</div>
</div>
</section>
{% schema %}
{
"name": "Prestations",
"settings": [
{ "type": "text", "id": "surtitre", "label": "Surtitre", "default": "Ce qu'on fait" },
{ "type": "text", "id": "titre", "label": "Titre", "default": "Nos prestations" },
{
"type": "select",
"id": "colonnes",
"label": "Colonnes",
"options": [
{ "value": "2", "label": "Deux" },
{ "value": "3", "label": "Trois" },
{ "value": "4", "label": "Quatre" }
],
"default": "3"
}
],
"blocks": [
{
"type": "prestation",
"name": "Prestation",
"settings": [
{ "type": "text", "id": "nom", "label": "Nom", "default": "Une prestation" },
{ "type": "textarea", "id": "description", "label": "Description" },
{ "type": "text", "id": "prix", "label": "Prix", "default": "sur devis" }
]
}
],
"max_blocks": 12
}
{% endschema %}#L’anatomie du fichier
Le nom du fichier est l’identifiant de la section
sections/prestations.liquidrépond au"type": "prestations"d’un template, et à{% section 'prestations' %}dans la coquille. Il n’y a pas d’autre déclaration à faire : le fichier suffit.Le balisage, en premier
Du HTML, avec des expressions Liquid dedans. Tout ce qui précède le
{% schema %}est rendu ; le blocschemalui-même est retiré avant le rendu.Le schéma, à la fin
Du JSON pur, entre
{% schema %}et{% endschema %}. Par convention il est posé en dernier, et c’est ainsi que Shopify le lit aussi. Voir Le bloc schema.
#Ce que la section reçoit
Au rendu, une section voit le contexte complet du site — site, page,
settings, menu, articles, annee — plus un objet section qui n’existe
que pour elle.
section.idchaîneL’identifiant de l'instance. Pour une section de template, c’est la clé
sous laquelle elle est déclarée ("tete", "corps"). Pour une section de
coquille, c’est son nom. Utile pour fabriquer un id HTML unique quand la
même section est posée deux fois.
section.typechaîneLe nom du fichier, sans sections/ ni .liquid.
section.settingsobjetLes réglages de cette instance : les default du schéma, recouverts par les
valeurs enregistrées. Voir Les types de réglage.
section.blockstableauLes blocs, dans l’ordre. Chaque entrée porte id, type et settings. Voir
Les blocs.
Une section ne voit pas les autres sections de la page, ni le HTML déjà
rendu. Elles sont rendues en parallèle et concaténées ensuite : rien ne
circule de l’une à l’autre, pas même par {% assign %}.
#Les deux façons d’appeler une section
#Depuis un template — une instance par entrée
C’est le cas courant. Le template déclare l’instance, ses réglages et ses blocs :
{
"sections": {
"nos-services": {
"type": "prestations",
"settings": { "titre": "Nos services", "colonnes": "2" },
"blocks": {
"b1": { "type": "prestation", "settings": { "nom": "Dépannage" } },
"b2": { "type": "prestation", "settings": { "nom": "Installation" } }
},
"block_order": ["b1", "b2"]
}
},
"order": ["nos-services"]
}La même section peut être posée plusieurs fois sur une page, sous deux clés différentes, avec des réglages différents. Voir Les templates.
#Depuis la coquille — le groupe header et footer
L’en-tête, le pied et la barre d’annonce ne sont dans aucun template : ils
doivent apparaître sur toutes les pages. C’est la coquille qui les pose,
avec {% section 'nom' %}, et leurs valeurs vivent dans
config/settings_data.json sous current.sections.
{% section 'annonce' %}
{% section 'entete' %}
<main id="contenu">{{ content_for_layout }}</main>
{% section 'pied' %}Ces sections portent par convention "group": "header" ou "footer" dans
leur schéma :
{% schema %}
{
"name": "En-tête",
"group": "header",
"settings": [
{ "type": "text", "id": "marque", "label": "Nom affiché", "info": "Vide : le nom du site est utilisé." },
{ "type": "text", "id": "horaires", "label": "Horaires du jour", "default": "Ouvert 7 h – 19 h 30" }
]
}
{% endschema %}group est aujourd’hui purement documentaire : le moteur ne le lit pas.
Ce qui décide qu’une section est posée par la coquille, c’est le
{% section %} du layout, et rien d’autre. Écris-le quand même — il dit à qui
relira le thème où cette section apparaît, et il sera lu le jour où un
panneau de réglages existera.
#Les motifs qu’on retrouve dans les quatre thèmes
#Masquer un élément vide plutôt que d’afficher un trou
{%- if section.settings.texte != blank -%}
<p class="chapeau">{{ section.settings.texte }}</p>
{%- endif -%}blank couvre à la fois la chaîne vide et la variable absente. C’est ce qui
permet à un client de vider un champ pour faire disparaître un élément, sans
laisser une balise vide qui décale la mise en page.
#Une classe pilotée par un select
<section class="section section-{{ section.settings.fond | default: 'papier' }}">Le réglage vaut papier, voile, encre ou accent ; la feuille de style
définit les quatre classes. Le default: protège du cas où le réglage n’a
jamais été renseigné et n’a pas de default dans le schéma.
#Les tirets qui mangent les espaces
{%- if … -%} supprime les blancs autour du tag. Sans eux, une boucle sur
douze blocs sème douze lignes vides dans le HTML rendu. Ce n’est pas
cosmétique dans un <span> : un blanc de trop dedans se voit à l’écran.
#Réagir à l’envoi d’un formulaire
{%- if page.demande == 'merci' -%}
<p class="message message-ok" role="status">
Merci, votre message est bien arrivé.
</p>
{%- elsif page.demande == 'erreur' -%}
<p class="message message-ko" role="alert">
Le message n'a pas pu être envoyé.
</p>
{%- endif -%}page.demande est renseigné après un envoi de formulaire. C’est ce qui permet
de remercier sans une ligne de JavaScript : le formulaire poste vers
/api/contacts, la route redirige, la page se rend à nouveau.
#Boucler sur les articles du CMS
{%- if articles.size > 0 -%}
{%- for article in articles limit: section.settings.nombre -%}
<h3><a href="{{ article.adresse }}">{{ article.titre }}</a></h3>
<span class="date">{{ article.date | date_fr }}</span>
{%- endfor -%}
{%- endif -%}articles vient du CMS, pas du thème. Un range dans le schéma décide
combien on en affiche. Voir Objets.
#Ce qui se passe quand une section échoue
Rien ne tombe en page blanche. La section fautive est remplacée par un commentaire HTML, et le reste de la page rend normalement.
<!-- section inconnue : bandeau-promo -->
<!-- section prestations : tag "for" not closed, line:14, col:1 -->
<!-- section absente : entete -->| Commentaire | Cause |
|---|---|
section inconnue : <type> | Le template demande un type dont le fichier n’existe pas. |
section absente : <nom> | {% section 'nom' %} sans fichier correspondant. |
section <type> : <message> | La section existe mais son rendu a levé une erreur. |
Ces commentaires sont le premier endroit à regarder quand un bloc de page a
disparu sans explication. Ouvre le code source de la page — pas
l’inspecteur, qui ne montre pas toujours les commentaires — et cherche
<!-- section.
#Les erreurs fréquentes
Un id de réglage qui ne correspond pas{{ section.settings.titre }} avec un schéma qui déclare "id": "title"
rend du vide, sans erreur. C’est de loin la cause numéro un d’un « réglage qui
ne marche pas ».
Un JSON de schéma invalideLa section reste rendable, mais sans aucun réglage : plus de valeurs par
défaut, section.settings ne contient que ce que le template a enregistré.
Très visible, donc vite corrigé. Voir Le bloc schema.
Deux blocs schema dans le même fichierSeul le premier est lu, et lui seul est retiré du rendu. Le second sera rendu
tel quel et fera échouer la section avec tag "schema" not found.
Un section.settings lu dans un snippet{% render 'ma-carte' %} n’hérite de rien : le snippet ne voit ni
section, ni settings, ni site. Passe ce dont il a besoin en arguments.
Voir Snippets.
#La vérification à l’enregistrement
L’API refuse d’écrire un .liquid dont la syntaxe ne s’analyse pas, avec le
message de l’analyseur — fichier, ligne, colonne. Le contrôle porte sur la
syntaxe, pas sur le sens : {{ nawak }} passe, comme chez Shopify, et
rend du vide.
node scripts/theme.mjs pousser✗ sections/hero.liquid — tag "for" not closed, line:14, col:1 [syntaxe]Le {% schema %} est retiré avant l’analyse, exactement comme au rendu — un
schéma au JSON invalide ne bloque donc pas l’enregistrement du fichier.

