Plantillas por dentro
Una plantilla es HTML con Liquid, SCSS y unos campos en JSON. Tú haces el molde; quien edita rellena los campos y no puede romper el diseño.
-
Cómo encaja todo
Una página de Layo es una pila de secciones. Cada sección es una plantilla rellenada: la plantilla pone el diseño y los campos; quien edita pone el contenido.
Pieza Qué es Plantilla El molde: campos, HTML, SCSS y JS Sección Una plantilla puesta en una página, con su contenido Tema Colores, fuentes y medidas de toda la web Bloque Una sección guardada para usarla en varias páginas Kit Una página entera guardada para crear otras iguales El servidor pinta el HTML (Liquid) y compila el SCSS; en el navegador no hay framework. Cada página carga solo el CSS y el JS de las secciones que tiene.
-
Dónde se hacen
En Desarrollo › Plantillas creas una nueva, clonas una de serie para cambiarla sin tocar la original, o importas un
.json. El editor tiene una pestaña por pieza:Pestaña Qué va General Nombre, posición, categoría y descripción Campos · Contenido JSON con lo que rellena quien edita → configuration.*Campos · Estilos JSON con las opciones de diseño → stylesConfiguration.*HTML El molde, con Liquid SCSS Su aspecto. Se compila al guardar JS Opcional. Se ejecuta una vez por cada sitio donde sale El editor de código es el de VS Code y autocompleta los campos y los filtros. Al guardar se comprueban el JSON, el Liquid, el SCSS y el JS: si algo falla, no se guarda y te dice dónde.
TrucoSi la plantilla ya está en páginas, al guardarla el cambio sale en todas a la vez.
-
La posición
Dice dónde se puede usar la plantilla:
positionPara qué bodySección normal de una página (la mayoría) moduleMódulo dentro de una columna: título, texto, botón… header/footerLa cabecera o el pie de toda la web postLa cabecera de las entradas del blog entryLa página de cada ficha de una colección product/cartLa ficha de producto y el carrito de la tienda -
Los campos
Cada pestaña de campos es una lista en JSON. Cada campo lleva
name,labelytype, y casi siempre undefault: el contenido de ejemplo al añadir la sección, que también sale en la miniatura de la biblioteca. Ponlo realista.Los tipos:
text,textarea,wysiwyg(texto con formato),number,date,link,image,select,boolean,color,color-scheme,menu,form,collection,code,multiple(una lista con sus propios campos) yseparator(un título para ordenar el formulario).[ { "name": "title", "label": "Título", "type": "text", "default": "Por qué trabajar con nosotros" }, { "name": "intro", "label": "Entradilla", "type": "textarea", "help": "Una o dos frases." }, { "name": "items", "label": "Tarjetas", "type": "multiple", "itemName": "tarjeta", "itemLabel": "title", "fields": [ { "name": "title", "label": "Título", "type": "text" }, { "name": "text", "label": "Texto", "type": "textarea" } ], "default": [ { "title": "Presupuesto en 24 horas", "text": "Nos cuentas qué necesitas y al día siguiente tienes el precio." }, { "title": "Sin sorpresas", "text": "El precio que firmas es el que pagas." } ] }, { "type": "separator", "label": "Botón (opcional)" }, { "name": "buttonLink", "label": "Enlace del botón", "type": "link", "default": "#contacto" } ]TrucoEl name solo lleva letras, números y _, no empieza por número y no se repite. Es el nombre que usas en el HTML.
-
Contenido o estilos
Contenido es lo que dice la sección: textos, fotos, enlaces, listas. Estilos es cómo se ve, siempre con opciones cerradas (
selectyboolean): esquema de color, espaciado, columnas, lado de la foto, animar o no.En Estilos no van colores libres ni medidas a mano: para eso están el tema y la pestaña Diseño. Así quien edita no puede salirse de la marca. El botón «Insertar estilos estándar» añade los de casi todas:
[ { "name": "colorScheme", "label": "Esquema de color", "type": "color-scheme", "default": "theme-cs-background" }, { "name": "spacing", "label": "Espaciado vertical", "type": "select", "default": "normal", "options": [{ "value": "compact", "label": "Compacto" }, { "value": "normal", "label": "Normal" }, { "value": "large", "label": "Amplio" }] }, { "name": "animate", "label": "Animar al hacer scroll", "type": "boolean", "default": true } ] -
El HTML, con Liquid
Layo usa Liquid, el lenguaje de plantillas de Shopify:
{{ … }}pinta un valor y{% … %}es lógica. Lo de Contenido llega comoconfiguration.*y lo de Estilos comostylesConfiguration.*.Normas
- Un solo elemento raíz, con la clase de la plantilla.
- Cada campo dentro de un
{% if %}: si se deja vacío, no queda una etiqueta vacía. {{ }}escapa el HTML.| rawsolo con los camposwysiwygycode, que ya llegan limpios.- Lo que va en atributos sale de listas cerradas (un
select), nunca de un texto libre. - Un solo
<h1>por página, en la portada. Las demás secciones empiezan por<h2>.
<section class="ej-ventajas {{ stylesConfiguration.colorScheme | default: 'theme-cs-background' }} space-{{ stylesConfiguration.spacing | default: 'normal' }}"> <div class="theme-container"> {% if configuration.title %}<h2 class="ej-ventajas__title">{{ configuration.title }}</h2>{% endif %} {% if configuration.items.size > 0 %} <ul class="ej-ventajas__list" role="list"{% if stylesConfiguration.animate %} data-fx="fade-up" data-fx-stagger{% endif %}> {% for item in configuration.items %} <li class="ej-ventajas__card"> <span class="ej-ventajas__num" aria-hidden="true">{{ forloop.index }}</span> {% if item.title %}<h3>{{ item.title }}</h3>{% endif %} {% if item.text %}<p>{{ item.text }}</p>{% endif %} </li> {% endfor %} </ul> {% endif %} {% if configuration.buttonLink %}<a class="theme-btn" href="{{ configuration.buttonLink }}">Pide presupuesto</a>{% endif %} </div> </section> -
Lo que tiene a mano
Variable Qué es section.idEl id único de esta sección en la página page.title,page.slugLa página donde está site.name,site.urlLa web site.contactTeléfono, email, dirección y WhatsApp de Ajustes site.hours.rowsEl horario de Ajustes vars.<nombre>Las variables de Sitio › Variables collections.<id>.itemsLas fichas publicadas de una colección Además de los filtros de Liquid, Layo trae los suyos:
media(una foto con sus versiones pequeñas),media_tagged(las fotos con unas etiquetas),video(YouTube y Vimeo con una portada ligera),latest_posts(las últimas entradas del blog) yt(traduce un texto fijo al idioma de la página).Una foto bien puesta, con su tamaño reservado y carga diferida:
{% if configuration.image %}{% assign img = configuration.image | media %} <img src="{{ img.url }}"{% if img.srcset %} srcset="{{ img.srcset }}" sizes="(max-width: 640px) 100vw, 50vw"{% endif %}{% if img.width %} width="{{ img.width }}" height="{{ img.height }}"{% endif %} alt="{{ configuration.imageAlt | default: img.alt }}" loading="lazy" decoding="async"> {% endif %}TrucoPara el teléfono, el email o el horario, léelos de site.contact y site.hours en vez de crear campos: así no se escriben dos veces.
-
El SCSS y el tema
Todo el CSS de la página va junto, así que cada plantilla usa clases con su propio prefijo (
.ej-ventajas,.ej-ventajas__card). Nunca selectores sueltos comoh2 {}.Los colores, las fuentes y las medidas salen del tema con variables:
--theme-color-primary,--theme-color-on-primary,--theme-color-background,--theme-color-on-background,--theme-color-background-variant,--theme-font-heading,--theme-font-body,--theme-radius,--theme-spacey--theme-container. Si se cambia el tema, la plantilla se adapta sola.Ya existen
theme-container, los esquemastheme-cs-background,theme-cs-background-variant,theme-cs-primaryytheme-cs-secondary, y los botonestheme-btnytheme-btn--ghost. Cortes:1023pxpara tablet y640pxpara el móvil..ej-ventajas { --space: 2; &.space-compact { --space: 1; } &.space-large { --space: 3; } padding: calc(var(--theme-space) * var(--space)) 0; &__title { margin: 0 0 32px; font-family: var(--theme-font-heading); font-size: clamp(30px, 4vw, 48px); } &__list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 0; padding: 0; list-style: none; } &__card { padding: 28px; border-radius: var(--theme-radius); background: var(--theme-color-background-variant); } &__num { color: var(--theme-color-primary); font-weight: 700; } @media (max-width: 1023px) { &__list { grid-template-columns: 1fr 1fr; } } @media (max-width: 640px) { &__list { grid-template-columns: 1fr; } } }TrucoNo hace falta escribir nada para «reducir movimiento»: Layo ya quita las animaciones a quien lo tiene activado.
-
JS y animaciones
El JS de una plantilla se ejecuta una vez por cada sitio de la página donde sale, al final de la página.
eles el envoltorio de esa sección: busca siempre dentro de él, porque puede haber dos copias de la misma sección. Solo se carga en las páginas que la usan, y si falla no rompe las demás.La sección tiene que verse y servir sin JS. El JS solo mejora: carruseles, filtros, cuentas atrás.
Para animar al hacer scroll no hace falta JS: pon
data-fxen cualquier etiqueta (fade-up,fade,slide-left,slide-right,zoom,bluroreveal), condata-fx-delaypara retrasarla ydata-fx-staggerpara que los hijos entren uno tras otro.const list = el.querySelector('.ej-carrusel__list'); for (const b of el.querySelectorAll('[data-dir]')) { b.addEventListener('click', () => list.scrollBy({ left: list.clientWidth * Number(b.dataset.dir), behavior: 'smooth' })); } -
Formularios
Con un campo de tipo
form, quien edita elige uno de sus formularios yconfiguration.formllega con todo: la dirección de envío, el antispam, los campos con su tipo y su error, y el mensaje de gracias.Copia el HTML de la plantilla de serie Formulario o Contacto con formulario y cambia solo el diseño. Funciona sin JavaScript y valida en el servidor.
-
Importar: una, varias o una web entera
Qué quieres meter Dónde Archivo Una plantilla Desarrollo › Plantillas › Importar… Un .jsoncon unaVarias a la vez El mismo botón Un .jsoncon todasUna web entera Administración › Webs › Exportar e importar › Importar El .zipde «Descargar .zip»El
.jsones el mismo que dan Exportar y Exportar todas. Cada plantilla se comprueba como al guardarla: si una falla, no entra ninguna. Si elidya existe, Layo pregunta si actualizarla (las páginas conservan su contenido) o importarla como copia.Una web a medida se hace así: se divide el diseño en secciones, una plantilla por sección con un prefijo común (
ac-cabecera,ac-portada…), todas en un solo.json. El.ziplo crea Layo al exportar una web montada y lleva el CSS ya compilado: no se escribe a mano.{ "format": "layo-templates", "version": 1, "templates": [ { "id": "ej-ventajas", "name": "Ventajas en tarjetas", "description": "Título, entradilla y tarjetas numeradas. Botón opcional.", "category": "Contenido", "position": "body", "fields": [], "styleFields": [], "html": "<section class=\"ej-ventajas\">…</section>", "scss": ".ej-ventajas { … }", "js": "" } ] } -
Antes de darla por buena
- Todos los campos tienen un
defaultrealista y la miniatura de la biblioteca se ve bien. - Vaciando cualquier campo no quedan huecos ni etiquetas vacías.
- Clases con prefijo propio, y ningún color, fuente ni radio escrito a mano: todo con
var(--theme-…). - Se ve bien a 1440, 768 y 390 píxeles, sin scroll horizontal en el móvil.
- Un solo
<h1>, y solo en portadas. - Ningún
| rawen un texto normal. - Funciona sin JavaScript, y el foco del teclado se ve.
- Todos los campos tienen un