← La bibliothèque

Fornella

Site d’une page pour un restaurant italien au feu de bois

Template complet Réservé aux membres Ouvrir la démo Débloquer la bibliothèque
Aperçu du template Fornella : deux photographies inclinées encadrent une cuisine au feu de bois allumée, le titre « Where Every Meal Becomes a Memory » au-dessus d’un bouton « Book a table today », sur un fond blanc cassé chaud.

Ce que c’est

Un site complet pour un restaurant : un accueil qui s’ouvre à mesure qu’on y descend, quatre plats qui arrivent par les coins et se rangent en grille, un bandeau de mots qui défile, quatre catégories, une carte, trois avis, une FAQ, trois articles et une bande Instagram. Une page, un fichier HTML, 811 lignes.

Ce qui fait ce template, c’est que cinq de ses neuf sections sont des scènes de défilement : une piste haute portant une scène épinglée en haut de l’écran, où tout ce qui bouge est piloté par un seul nombre--p, la progression dans la piste, de 0 à 1. Le JavaScript écrit ce nombre et s’arrête là ; le CSS fait le reste. Aucune bibliothèque d’animation, aucune bibliothèque de défilement, et pas non plus d’animation-timeline — celle-ci n’existe que dans Chrome. 394 lignes de JavaScript pour l’ensemble, et la page se lit sans elles.

Le dessin vient d’un gabarit Webflow pour un restaurant dont il ne reste aucune image : les photographies ont été régénérées pour ce template. Chaque ligne de code a été réécrite — jQuery, le moteur d’animation propriétaire IX2 et son magasin de keyframes, le CSS minifié, et le style="opacity:0" posé en ligne sur chaque bloc animé, que bloque une politique de sécurité stricte, laissant une page blanche.

C’est tout l’intérêt : ce template n’est pas là pour être admiré, il est là pour être lu, cassé et remonté.

Ce que tu changes en premier

Les couleurs — l’accent, c’est trois teintes

Tout en haut de assets/css/style.css :

--ink:        #3b2f2f;  /* titres, texte fort */
--paper-off:  #f5f5f5;  /* le vrai fond de la page */
--paper-warm: #f4e1d2;  /* les blocs crème */
--night:      #1c1c1c;  /* la moitié sombre de la page */
--ember:      #bf4f22;  /* l’accent, 4,82:1 sur blanc */
--ember-deep: #93331f;  /* le même, plus foncé — survol, petit texte sur crème */
--ember-glow: #ea9b6e;  /* le même, éclairci — le seul lisible sur une photo */

Une chose à comprendre avant de toucher au reste : il y a trois braises, pas une. --ember passe le AA sur blanc (4,82:1) mais disparaît sur un panneau sombre ; c’est --ember-glow qui prend le relais là (5,76:1 sur --ink). Si tu en changes une, change les trois, sinon quelque chose devient illisible à un endroit que tu ne regardes pas.

Le nom

Chercher « Fornella » dans index.html : l’en-tête, le titre, les avis, le pied de page. Aucun nom de classe ne contient la marque — un rechercher-remplacer ne peut rien casser. Le logo est un SVG de quatre tracés dans l’en-tête : l’arche d’un four sur un lit de braises.

Les tailles

L’échelle typographique est déclarée une fois en haut, puis redéclarée à chaque point de rupture (991, 767 et 479 px). Un titre ne porte donc jamais sa propre requête de média : change --h1 et toute la page suit — 80 px sur grand écran, 40 px sur un téléphone. Les valeurs sont celles mesurées sur l’original à chaque largeur.

Les cinq scènes, et comment elles sont faites

Elles n’ont pas été regardées, elles ont été lues : un export Webflow garde tout son moteur d’animation dans un magasin JavaScript, accessible par Webflow.require('ix2').store.getState().ixData. On en sort les keyframes exacts — pourcentages, pixels, degrés, couleurs — de chaque bloc qui bouge. Chaque scène ci-dessous est une section de 2 500 px portant une scène d’un écran ; les nombres de la colonne du milieu sont ceux de l’original.

ScèneKeyframes d’origineComment
Accueilles deux photos latérales vont à x ±50 à 40 %, puis x ∓20 / y +200 et scale 0,6 à 60 %, en tournant de 20° à 10° ; le cadre central passe de 40 %×35 % au plein cadre ; le texte passe du brun au blanc entre 50 % et 60 % ; le fond bascule au noir à 65 %--p les pilote toutes, listes de keyframes interpolées en huit lignes de JavaScript
Savoir-fairequatre plats attendent à x ±130 / y ±100, apparaissent à 45 %, se posent à 50–55 % ; le bloc du milieu passe de l’échelle 0,5 à 1 entre 50 % et 65 % ; un cercle de texte monte de y +100 à −1000même mécanisme, une propriété personnalisée par plat
Avisle mot grandit, tient, puis sort du cadre pendant que trois cartes s’empilent par le bas, chacune se redressant en arrivantidem, plus une rotation qui revient à zéro
FAQle mot FAQ dérive vers le haut derrière le contenu ; deux vignettes arrivent de hors-champ et se posent à côté du titreidem ; les questions, elles, sont des <details> natifs
Instagramcinq photos montent en rang, puis toute la bande glisse latéralement pour le reste de la pistela bande glisse d’une fraction de son propre débordement : elle s’arrête donc toujours avec sa dernière vignette au bord droit, jamais dans le vide
Bandeaudeux rangées de mots qui glissent en sens inverse, en bouclela liste est écrite deux fois ; l’animation translate exactement de la moitié de la bande, la boucle n’a donc pas de couture
Catégoriessurvoler une ligne fait monter une petite photosurvol CSS ; la photo est en aria-hidden — elle décore, elle ne porte jamais une information que le texte ne donne pas déjà

Ce qu’il faut savoir

Aucune requête externe, aucune étape de build. On ouvre index.html dans un navigateur et ça marche. Polices auto-hébergées, photographies locales, aucun CDN, aucun traceur.

Supprime le JavaScript et tu obtiens le même contenu, en fixe. Tous les états masqués sont écrits sous html.js, et enhance.js — douze lignes — est la seule chose qui pose cette classe. Sans les scripts, les scènes ne sont que neuf sections les unes après les autres, le menu s’ouvre, la FAQ s’ouvre, et la bande Instagram se fait toujours glisser au doigt.

La carte et la FAQ sont des <details> natifs. Ils s’ouvrent au clic, au clavier et par la recherche du navigateur, qui sait atteindre l’intérieur d’un panneau fermé. Le JavaScript ne fait qu’animer la hauteur.

Sous 767 px, les scènes cessent d’être des scènes. Épingler une scène et faire défiler 2 500 px au travers, c’est cinq écrans de pouce par section. À cette largeur les pistes s’effondrent et chaque pièce est déjà à son état final. Le script lit la requête de média et ne mesure même pas.

Sous une politique de sécurité stricte (script-src 'self'; style-src 'self') : aucun style en ligne, aucun script en ligne, aucun onclick. Le dossier embarque une copie des en-têtes réels du site pour que le banc local serve la page dessous.

Accessibilité : lien d’évitement, aria-expanded tenu à jour sur le menu, photographies décoratives en aria-hidden, le compteur de commande doublé d’une phrase lue par les lecteurs d’écran, et prefers-reduced-motion respecté — les scènes se lisent alors à leur état final au lieu d’être pilotées.

Ce qui n’est pas parfait

Le panier est une décoration. L’original est un gabarit e-commerce : vrai panier, paiement, état de commande. Ici l’icône porte un zéro et pointe vers la carte. Un panier qui fait semblant de marcher est pire que pas de panier — branche-le sur ton propre service, ou retire l’icône.

L’original était un site multi-pages. Tout est replié en ancres de la page unique plutôt que laissé à pointer vers des 404.

Un seul nombre n’est pas une timeline. Piloter une scène avec --p se lit simplement et coûte peu, mais cela attache toutes les pièces d’une scène à la même progression. Deux éléments qui devraient bouger sur des rythmes différents demandent deux listes de keyframes, pas deux timelines — ce que fait l’original lui aussi, et c’est bien pourquoi son magasin est lisible.

L’accent a bougé. Le rouge signature de l’original est la seule couleur qu’on ne peut pas reprendre telle quelle ; il a fait six degrés sur la roue et perdu en clarté, jusqu’à la terre cuite. Côte à côte, la page est d’un ton plus chaud que sa référence.

Il t’attend dans la bibliothèque.

Fornella est compris dans l’abonnement, avec le reste de la bibliothèque et la formation complète.

Accès immédiat · Sans engagement · Résiliable en un clic