Esta carpeta contiene todo los archivos de estilos: css y scss, archivos de comportamientos JavaScript, imágenes incluidas dentro del theme y el archivo checkout.scss.tpl.
CSS
Lógica
En nuestro Base Theme, utilizamos como estructura general Bootstrap 4, solo utilizando la grilla: https://getbootstrap.com/docs/4.3/layout/grid/ y las “utilities clases”. Siguiendo los lineamientos que la misma nos propone:
- Organización de columnas: 12
- Prioridad mobile y media queries para desktop
- Estructura container - row - col
- Utilización de helpers/utilities
Utilizamos la misma lógica para los elementos propios. Asignamos un nombre para para encapsular un componente al que llamamos bloque (block), que contiene elementos (element) con la posibilidad de que tengan variantes (modifier). Los tres términos se separan por guión medio. Por ejemplo:
.page{} .page-title{} .page-title-primary{}
Por ejemplo este block, es el componente que arma la Página (page), su elemento interior es el Título (title) que va a contemplar las propiedades generales, como podrían ser: position, font-family, padding, margin; y por último el modifier “primary” que podría modificar o agregar variaciones, como: color y tamaño.
Pueden existir elementos que sean independientes de los bloques, como un botón:
.btn{} .btn-primary{}
Utilizamos los nombres de los componentes para las clases, para poder reutilizarlas y no trabajar con nombres apuntados a features específicos.
Por ejemplo:
No usamos nombre de features
.billing-card { }
Usamos nombres de componentes
.card { } .card-primary { } .card-secondary { }
Hay excepciones en las que los nombres pueden ser más específicos, ya que son utilizados únicamente en un lugar.
Además de tener clases para componentes y variaciones a través de los modifiers, disponemos de clases llamadas “helpers” o “utilities”, que por lo general tiene 1 única propiedad y las utilizamos para aplicar una excepción a las propiedades del componente.
Por ejemplo tenemos un componente para títulos que tiene la propiedad “text-align: center” para que siempre su contenido se muestre centrado:
.page-title{ css-property; css-property; css-property; text-align: center; }
<h1 class=”page-title”>Título</div>
Pero en una pantalla específica, necesitamos que ese título esté alineado a la izquierda. Para eso, no vamos a crear una nueva clase, sino que vamos a utilizar un helper:
<h1 class=”page-title text-left”>Título</div>
Tenemos que tener bien claro, que el uso de un Helper responda a una excepción a la regla, porque sino sería conveniente crear un elemento nuevo o una variación nueva, para que no suceda esto:
<h1 class=”page-title mt-1 mb-1 text-left bg-red color-primary”>Título</h1>
También utilizamos SASS, sobretodo para propiedades como colores, fuentes y configuraciones que se repiten en diferentes elementos y componentes.
En el archivo SASS style-colors.scss.tpl guardamos los colores y tipografías configuradas desde la sección de Personalización del diseño en el Administrador nube y lo aplicamos a todos los estilos necesarios:
{# /* // Colors */ #} $primary-color: {{ settings.primary_color }}; $main-foreground: {{ settings.text_color }}; $main-background: {{ settings.background_color }}; {# /* // Font families */ #} $heading-font: {{ settings.font_headings | raw }}; $body-font: {{ settings.font_rest | raw }};
También aprovechamos los SASS para anidar componentes y funciones, como por ejemplo:
@mixin prefix($property, $value, $prefixes: ()) { @each $prefix in $prefixes { #{'-' + $prefix + '-' + $property}: $value; } #{$property}: $value; } a { color: $main-foreground; @include prefix(transition, all 0.4s ease, webkit ms moz o); &:hover, &:focus{ color: rgba($main-foreground, .5); } }
Tips
Acá te comentamos algunas buenas prácticas para mantener tu código prolijo y ordenado.
- Como la memoria siempre falla, intentamos comentar todo lo que podemos. Explicando cada sección y aclarando cada estilo. En nuestros .tpl los comentarios se ingresan de la siguiente manera:
{# /* Comentario */ #} - Las hojas de estilo tienen un índice inicial para ordenar los componentes y encontrarlos más rápido.
- Nosotros no utilizamos ID para identificar elementos, ya que hay algunas funciones que utilizan los IDs.
- No aplicamos CSS a elementos básicos como “div.” o “p.”. Excepto los títulos: h1, h2, h3, etc.
- Evitamos usar nombres de elementos y variaciones demasiado específicos para que no estén relacionados con algo que pueda cambiar. Por ejemplo, los colores.
- No usamos CSS para las clases que empiezan con js-, ya que estas funcionan con JavaScript.
- Seguimos una guia pàra mantener el orden y la logica de nuestro CSS: https://codeguide.co/#css sobre todo el orden de las propiedades: https://codeguide.co/#css-declaration-order
Utilización
En la carpeta CSS podés encontrar los tres archivos que le dan todos los estilos al theme.
Los estilos están separados en tres archivos diferentes por los siguientes motivos:
- Prioridad (crítico y no critico)
- Formato
- Contenido
style-critical.tpl
Este archivo contiene todos los estilos críticos para la visualización correcta de la tienda “Above the fold”. Se agrega inline dentro del DOM para que cargue antes que nada y el formato con el que está escrito es CSS simple.
style-colors.scss.tpl
Este .tpl contiene todos los parámetros de color y tipografías de la tienda en formato SCSS. Es crucial que desde el primer momento, los usuarios vean la tienda con los colores y fuentes institucionales de la marca, es por eso que funciona de forma sincrónica, cargando antes que el resto del HTML.
style-async.scss.tpl
Este es el único archivos de estilos que se carga de forma asincrónica y contiene todos los estilos y parámetros que no son necesarios para la creación y visualización del diseño en primera instancia (como por ejemplo: estilos aplicados a modales o menúes desplegables). Esta creado en SCSS y para que su carga sea asincrónica, es incluido en un archivo JS (“load-css-async.tpl”) que es llamado desde el layout.tpl:
load-css-async.tpl:
<script id="style-css"> loadCSS( '{{ 'css/style-async.scss.tpl' | static_url }}', document.getElementById("style-css")); </script>
layout.tpl:
{% include "static/js/load-css-async.tpl" %}
Para entender esta priorización de estilos podés ver el artículo de CSS + Performance
checkout.scss.tpl
Por último existe otro archivo de CSS que se encuentra fuera de la carpeta CSS pero dentro de Static. Acá se puede agregar o modificar CSS para el checkout, solo que para que apliquen estos cambios deben activar la opción de "Colores del checkout" en la sección Configuraciones/Opciones del checkout desde el administrador.
JS
Lógica
Los archivos JavaScript son fundamentales para el funcionamiento de nuestras tiendas, así como para generar comportamientos atractivos desde el diseño.
Mantenemos separado todo el código JS propio, que generamos nosotros para funciones particulares en el flujo de compra de las tiendas, y el código que nos facilitan plugins y aplicaciones externas.
Utilizamos por defecto jQuery y algunos plugins de código abierto que nos dan flexibilidad a la hora de desarrollar nuevos themes.
Dependiendo de la dependencia con jQuery, vamos a ubicar las funciones en diferentes .tpls
- external-no-dependences.js.tpl - No necesitan jQuery para funcionar
- external.js.tpl - Necesitan jQuery para funcionar
- store.js.tpl - Funciones propias
Por otro lado, tenemos una porción del código JS que es privado. No se puede modificar y no se encuentra disponible dentro de la estructura del theme.
Este código privado tiene las funciones fundamentales de Tiendanube, y las podes identificar porque comienzan con “LS.”. Muchas de ellas tienen que ver con el control del catálogo de productos, los medios de pago y los medios de envío.
En este archivo determinamos algunas funciones importantes que luego se pueden utilizar públicamente como las siguientes:
LS.ready.then - Espera que se cargue jQuery para luego cargar lo que esté dentro de esta función.
LS.ready.then(function(){ {# Libraries that requires Jquery to work #} {% include "static/js/external.js.tpl" %} {# Specific store JS functions: product variants, cart, shipping, etc #} {% include "static/js/store.js.tpl" %} });
LS.addToCartEnhanced - Cuando un producto es agregado al carrito.
function changeVariant(variant) - Cuando se selecciona otra variante en un producto. Se utiliza por ejemplo, para actualizar el precio si una variante es más cara que la otra.
LS.calculateShippingAjax - Cuando se realiza el cálculo del costo de envío.
Tips
Algunas recomendaciones que podemos darte:
- Siempre las clases que tienen prefijo “.js-” están asociadas a un comportamiento JavaScript. Si borras alguna, corrobora que no afecte al flujo de compra.
- Siempre que se agregue un código js respetar el index de cada archivo. Mantener el código ordenado facilita el entendimiento y la corrección de errores.
- Ubicar los plugins en los archivos external.js.tpl y dependiendo de la dependencia con jQuery agregarlo en external-no-dependencies.js.tpl
- Los JS generan uno de los principales problemas para mantener la performance de nuestras tiendas, por lo que tenes que asegurarte de no cargar js innecesario en las sección que no se utilice. Para esto se puede utilizar condicionales de Twig como:
{% if template == 'product' %} -- CODE javaScript -- {% endif%} para que solo se cargue este código en el detalle del producto. - Para más información de performance y JavaScript podés visitar el siguiente artículo
Utilización
Externals JS
Utilizamos algunos plugins para diferentes componentes de la tienda, logrando comportamientos y funcionalidades muy importantes en el flujo de ventas. Todos los códigos de estos plugins están ubicados en 2 archivos:
external.js.tpl
Este archivo contiene los siguientes códigos:
- Jquery.cookie v1.4.1 - Utilizado para poder determinar cada cuánto tiempo debe dispararse una acción. Nosotros lo utilizamos para el popup del newsletter.
Sitio del autor: https://plugins.jquery.com/cookie/ - Jquery.livequery v1.3.6 - Es utilizado para ejecutar funciones jQuery en tiempo real. Lo utilizamos en el calculador de envíos.
Sitio del autor: https://plugins.jquery.com/livequery/ - Fancybox 3.3.1 - Es un plugin para hacer zoom en imágenes generando un modal con diferentes opciones. Usamos este plugin en las imágenes del detalle del producto.
Sitio del autor: https://www.fancyapps.com/fancybox/3/
En este caso vas a observar que el código está contenido por el siguiente condicional: {% if template == 'product' %} {% endif%}. Esto significa que se va a cargar únicamente para la pantalla del detalle de producto, ya que es en el único lugar donde se utiliza este plugin.
También está contenido por un {% raw %}{% endraw %}. Esto es necesario ya que al ser un archivo .tpl, algunos códigos JS tienen una sintaxis conflictiva con Twig, por lo que todo lo contenido dentro de esta etiqueta no va a contemplar ningún mçetodo ni función de Twig. - Admin.externalcode - estas líneas van a llamar a los códigos personalizados que el administrador de la tienda puede agregar desde “Configuración > Códigos externos”
external-no-dependencies.js.tpl
En este archivo contiene los siguientes plugins:
- Lazyload - Es una librería con diferentes features que contemplan la carga progresiva y priorización de carga de imágenes. Lo utilizamos para la optimización de performance en relación a la carga de imágenes. Para una mayor información podes visitar nuestro artículo de imágenes - Performance
Sitio del autor: https://github.com/aFarkas/lazysizes - Instafeed - Lo usamos para mostrar las últimas publicaciones de Instagram dentro de cada tienda. Está contenido por el condicional {% if settings.show_instafeed and (template == 'home') %} para que únicamente se cargue en la página de inicio y teniendo habilitado el componente desde el administrador → Personalizar el diseño actual.
Sitio del autor: http://instafeedjs.com/ - Swiper 4.4.2 - Es un plugin dedicado para Sliders. Lo utilizamos para todos los carruseles de la tienda: carrusel de imágenes, carrusel de productos, productos relacionados, imágenes del detalle de producto.
Site del autor: https://idangero.us/swiper/
CSS async JS
Luego vamos a encontrar un .js para insertar hojas de estilo de forma asincrónica. Si te interesa saber cómo realizarlo, lo describimos más arriba.
Este archivo contiene la función y luego los llamados a los CSS de la siguiente manera:
<script id="font-awesome-css"> loadCSS( '{{ 'font-awesome/font-awesome-5.css' | static_url }}', document.getElementById("font-awesome-css")); </script> <script id="style-css"> loadCSS( '{{ 'css/style-async.scss.tpl' | static_url }}', document.getElementById("style-css")); </script>
JS del theme - store.js.tpl
Para completar con todos los .js de la carpeta, vamos a encontrar el archivo que contiene todos los comportamientos y funciones JavaScript propias del theme.
En el archivo store.js.tpl vamos a tener un index con todo el contenido de las tiendas que necesiten un comportamiento JavaScript, para poder encontrar rápidamente a qué corresponde cada código.
Siempre que necesitamos asignarle una funcionalidad a un elemento HTML, vamos a utilizar clases con el prefijo “js-”. Desde este archivo no usamos identificadores ID. Por ejemplo para los modales, definimos variables apuntadas a elementos con las clases “.js-modal-close” y “.js-modal-open”
var $modal_close = $('.js-modal-close'); var $modal_open = $('.js-modal-open');
Images
Imágenes
Las tiendas están llenas de imágenes, eso ya lo sabemos, desde imágenes publicitarias para banners, carruseles, feeds de instagram hasta las propias imágenes de los productos.
Podemos empezar a hablar de imágenes administrables y no-administrables. Las primeras van a ser todas aquellas que se carguen desde el Administrador de la Tienda, tanto desde un producto como desde la sección “Personaliza tu diseño actual”.
Y las no-administrables van a ser las que definimos desde el código directamente en el theme. Estas últimas, se van a encontrar en la carpeta static/images dónde van a ser llamadas desde los diferentes archivos con HTML.El tamaño de las imágenes va a ser el original de la imagen que se suba por FTP, por lo que hay que tener mucho cuidado en su optimización ya que podemos perjudicar mucho la performance de la tienda con la carga de una imagen muy pesada.
Se pueden subir imágenes en .png, .jpg y .gif y desde los archivos con html vamos a llamar a estas imágenes de la siguiente manera:
{{ "imagen.jpg" | static_url | img_tag (store.name) }}
El ALT de una imagen puede ser pasado como parámetro entre comillas
img_tag("<strong>Twitter</strong>")
Por otro lado las imágenes que se suben desde el Administrador nube, tienen otro comportamiento. Cuando se carga una imagen, esta se guarda en diferentes tamaños que podemos llamar y utilizar desde el Storefront, dependiendo el lugar y la funcionalidad que se necesite.
Los tamaños son los siguientes:
- tiny: 50px de ancho.
- thumb: 100px de ancho.
- small: 240px de ancho.
- medium: 320px de ancho.
- large: 480px de ancho.
- huge: 640px de ancho.
- original: 1024px de ancho.
- 1080p: 1920px de ancho. (solo para imágenes cargadas desde “Personalizar mi diseño actual”)
Si tenés que llamar desde el storefront a una imagen de producto, vamos a necesitar acudir al objeto “product” ubicado dentro del template product.tpl o dentro de un loop de productos como puede ser la grilla de productos en una categoría. Para entender mejor sobre los objetos producto visita product.tpl o snipplets/product-grid.tpl
Por ejemplo a la imagen principal de un producto, la podemos llamar de la siguiente manera:
<img alt="{{ product.featured_image.alt }}" src="{{ product.featured_image | product_image_url('tiny')}}" >
Donde determinamos la etiqueta <img>, y utilizamos el objeto product.featured_image. Y vamos a determinarle las siguientes propiedades a la imagen:
Alt: {{ product.featured_image.alt }}
Src: {{ product.featured_image | product_image_url('tiny')}}
En este caso estamos llamando al tamaño tiny, pero tranquilamente podríamos llamar a la large de la siguiente manera: <img alt="{{ product.featured_image.alt }}" src="{{ product.featured_image | product_image_url('large')}}" >
Pero, si tenes que mostrar en el storefront una imagen cargada desde la sección Personalizar mi diseño actual, vas a tener que recurrir a obtener el nombre del setting. Por ejemplo, si tenes una setting para la carga de imágenes como la siguiente:
Image original = banner.jpg title = Cargar imagen (JPG, GIF, PNG) width = 600 height = 600
Vamos a usar el siguiente código para mostrarla en la tienda:
{% if "banner.jpg" | has_custom_image %} <img src="{{ "banner.jpg" | static_url | settings_image_url('large') }}" > {% endif %}
Podés consultar más información de cómo crear y administrar los settings.txt en Config.
Tips
Verifica bien el tamaño de la imagen que llamas, para no cargar una imagen más grande de lo que se necesita. De esta manera vas a mejorar la performance de la tienda.
Te recomendamos utilizar Lazyload y srcset en todas las imágenes que utilices para mejorar la velocidad de carga y la experiencia de los usuarios. Mira toda la información necesaria en este artículo: Imágenes y Performance
checkout.css
IMPORTANTE! No modificar la ubicación de este archivo ya que la plataforma va a buscarlo en la carpeta static.
Este archivo va a contener todos los estilos que personalizan el diseño del checkout. Toma los parámetros ingresados en la Personalización del diseño actual, para aplicar las tipografías y colores que tiene toda la tienda.
El archivo ya tiene todos los estilos que existen en el checkout, por lo que no es necesario crear nuevos, excepto un pseudo elemento.
Para que el checkout utilice esta hoja de estilos hay que habilitarlo desde el Administrador nube. En “Configuraciones > Opciones de Checkout” tiene que estar tildada la opción “Usar los colores de tu diseño en el checkout” en la sección “COlores del Checkout.