#La coquille
layout/theme.liquid est le HTML qui entoure toutes les pages du site : le
doctype, la balise head, l’en-tête, le pied, et le trou dans lequel le
contenu de la page vient tomber. C’est le seul fichier de layout/ que le
moteur connaisse, et l’un des trois sans lesquels un thème ne rend rien.
Cette page le dissèque à partir de themes/origo/layout/theme.liquid, qui
tient en quarante-quatre lignes et fait tout ce qu’une coquille doit faire.
#Le fichier entier
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.titre }} — {{ site.nom }}</title>
{{ 'theme.css' | asset_url | stylesheet_tag }}
<style>
:root {
--encre: {{ settings.encre }};
--papier: {{ settings.papier }};
--accent: {{ settings.accent }};
--accent-sombre: {{ settings.accent | teinte: -18 }};
--accent-clair: {{ settings.accent | teinte: 88 }};
--largeur: {{ settings.largeur }}px;
--arrondi: {{ settings.arrondi }}px;
--bouton-rayon: {% if settings.boutons == 'droit' %}4px{% else %}999px{% endif %};
}
</style>
</head>
<body>
<a class="saut" href="#contenu">Aller au contenu</a>
{% section 'annonce' %}
{% section 'entete' %}
<main id="contenu">{{ content_for_layout }}</main>
{% section 'pied' %}
</body>
</html>L’original porte en plus un {%- comment -%} qui explique le bloc de
variables CSS, et trois réglages de typographie. Ils sont retirés ici pour la
lisibilité, pas parce qu’ils poseraient problème.
#{{ content_for_layout }} — le seul point obligatoire
Le moteur rend d’abord toutes les sections du template, concatène leur HTML,
puis rend la coquille avec cette chaîne dans content_for_layout. C’est la
mécanique de Shopify, et elle a l’avantage de laisser la coquille décider où
le contenu tombe et ce qui l’entoure.
Une coquille sans {{ content_for_layout }} rend une page sans contenu.
Sans erreur, sans avertissement : l’en-tête et le pied s’affichent, le milieu
est vide. Si une page paraît « ne rien afficher », c’est la première ligne à
chercher.
content_for_header n’existe pas dans Webcosa. Chez Shopify, il injecte
les balises de la plateforme dans le head. Ici il n’y a rien à injecter, et
la variable n’est pas définie : elle rendra une chaîne vide, silencieusement,
puisque le moteur tourne avec strictVariables désactivé. Ne le copie pas
depuis un thème Shopify en croyant qu’il fait quelque chose.
#Le head
#Le titre
<title>{{ page.titre }} — {{ site.nom }}</title>page.titre est le titre de la page courante, site.nom celui de
l’entreprise. Les quatre thèmes d’origine utilisent exactement cette forme.
Voir Objets.
#La feuille de style
{{ 'theme.css' | asset_url | stylesheet_tag }}Deux filtres à la suite. asset_url transforme un nom de fichier en
adresse servie, stylesheet_tag l’enveloppe dans une balise link. Le
résultat, pour un thème d’identifiant abc… :
<link rel="stylesheet" href="/theme-assets/abc123.../theme.css">asset_url prend le nom seul, jamais le chemin. L’adresse produite est
/theme-assets/<id-du-thème>/<nom> — un seul segment de nom — et c’est la
route qui remet le préfixe assets/ pour interroger la base.
Écrire {{ 'assets/theme.css' | asset_url }} fabrique une adresse à deux
segments qui ne correspond à aucune route. La feuille de style répond 404, et
la page rend quand même : du HTML nu, mais du HTML. Un site sans CSS ressemble
à un thème mal écrit, pas à une adresse fausse — c’est pour ça que le défaut a
tenu longtemps, sur tous les sites à la fois.
Voir Assets pour le détail de la route et de son cache, et Filtres pour les autres filtres maison.
#Les réglages posés en variables CSS
C’est la technique des quatre thèmes, et elle mérite d’être copiée : les
réglages globaux deviennent des variables CSS sur :root, ici et nulle
part ailleurs.
<style>
:root {
--encre: {{ settings.encre }};
--accent: {{ settings.accent }};
--accent-sombre: {{ settings.accent | teinte: -18 }};
--largeur: {{ settings.largeur }}px;
}
</style>Aucune section n’a alors besoin de connaître une couleur : elles héritent
toutes de :root, et la feuille de style dans assets/ reste un fichier CSS
ordinaire, sans une ligne de Liquid.
Le filtre teinte évite de multiplier les réglages : teinte: -18 assombrit
de 18 %, teinte: 88 éclaircit de 88 %. Sans lui, chaque nuance d’une
couleur réglable devrait être un réglage de plus, et un panneau de vingt
sélecteurs de couleur ne se remplit jamais.
Les unités s’écrivent hors de l’expression : {{ settings.largeur }}px
et non {{ settings.largeur | append: 'px' }}. Le réglage reste un nombre,
donc comparable et utilisable dans un {% if %}, et le CSS reste lisible.
Une condition Liquid peut aussi produire directement une valeur CSS :
--bouton-rayon: {% if settings.boutons == 'droit' %}4px{% else %}999px{% endif %};C’est ce que fait origo pour la forme des boutons, la police des titres et
la casse des surtitres. Un select dans le schéma, une variable CSS dans la
coquille, et toute la feuille de style suit.
#Le body
#Le lien d’évitement
<a class="saut" href="#contenu">Aller au contenu</a>Premier élément focalisable de la page, visuellement masqué jusqu’à ce qu’il
reçoive le focus. Les quatre thèmes le posent, et l’ancre #contenu
correspond au <main id="contenu"> plus bas. Ce n’est pas une exigence du
format, c’est une exigence d’accessibilité — et il coûte une ligne.
#{% section %} — l’en-tête et le pied
{% section 'annonce' %}
{% section 'entete' %}
<main id="contenu">{{ content_for_layout }}</main>
{% section 'pied' %}Le tag {% section 'nom' %} rend sections/nom.liquid depuis la
coquille, c’est-à-dire hors de tout template. Sans lui, il faudrait écrire
l’en-tête et le pied en dur ici, donc les sortir de l’éditeur et du schéma :
le client ne pourrait plus changer son numéro de téléphone sans toucher au
code.
Ce que la section reçoit :
section.idchaîneLe nom passé au tag. {% section 'entete' %} donne entete.
section.typechaîneLe même nom. Pour une section de coquille, id et type sont identiques —
il n’y a qu’une instance par nom.
section.settingsobjetLes valeurs lues dans config/settings_data.json, sous
current.sections.<nom>.settings, par-dessus les default du schéma de
la section.
section.blockstableauLes blocs lus sous current.sections.<nom>.blocks, ou un tableau vide.
Pour une section de coquille, blocks est passé tel quel : ce doit donc
être un tableau d’objets { "type": …, "settings": … } dans
settings_data.json, et non l’objet indexé par identifiant qu’utilisent les
templates. C’est la seule asymétrie du format, et elle n’est écrite nulle
part ailleurs. Voir Les blocs.
Une section absente ne casse rien : le tag rend un commentaire HTML
<!-- section absente : nom -->. Une section qui lève une erreur rend
<!-- section nom : message -->. Et l’imbrication est bornée à six niveaux,
compteur hors de portée du thème — détails dans
Le bac à sable.
#Ce que la coquille voit, et ce qu’elle ne voit pas
La coquille est rendue avec le contexte complet : site, page,
settings, menu, articles, annee, theme_base, plus
content_for_layout.
Elle ne voit pas section — il n’y a pas de section en cours à ce
niveau. {{ section.settings.titre }} dans la coquille rend du vide.
Un {% schema %} dans layout/theme.liquid casse la page : schema
n’est pas un tag reconnu, et le fichier est rendu tel quel, sans que le bloc
ne soit retiré comme il l’est pour les sections. L’erreur remontée est
tag "schema" not found. La coquille n’a pas de réglages propres — ceux dont
elle a besoin sont les réglages globaux.
#Une coquille minimale qui fonctionne
Pour démarrer, ou pour isoler un problème :
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.titre }} — {{ site.nom }}</title>
{{ 'theme.css' | asset_url | stylesheet_tag }}
</head>
<body>
{{ content_for_layout }}
</body>
</html>#Les erreurs qui se voient le moins
content_for_layout oubliéLa page s’affiche, l’en-tête et le pied aussi, et le contenu n’est nulle part. Aucune erreur.
asset_url avec le chemin completLe site rend en HTML nu. La page fonctionne, elle est juste sans style. À
vérifier dans l’onglet réseau : un 404 sur /theme-assets/…/assets/theme.css.
Une variable mal orthographiée{{ settings.acent }} rend une chaîne vide. Le moteur tourne avec
strictVariables désactivé, exprès : une faute de frappe dans un coin de
pied de page ne doit pas éteindre la page entière. Traître en développement,
salutaire en production.
Une section de coquille absente du thème{% section 'annonce' %} sans sections/annonce.liquid rend un commentaire
HTML. Invisible à l’écran, lisible dans le code source de la page.

